1. 何為建造者模式
定義:將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表現(xiàn)分離,使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表現(xiàn)者冤。
建造者模式負(fù)責(zé)將構(gòu)建復(fù)雜對(duì)象的過(guò)程和它的部件解耦肤视,也就是過(guò)程和部件的解耦。比如說(shuō)汽車(chē)涉枫,是一個(gè)很復(fù)雜的對(duì)象邢滑,它有很多的部件,車(chē)輪愿汰、發(fā)動(dòng)機(jī)困后、座椅、車(chē)門(mén)衬廷、郵箱等等摇予;它的組裝過(guò)程也很復(fù)雜(需要專(zhuān)業(yè)人士按照步驟進(jìn)行裝配),建造者模式就是為了將部件和組裝過(guò)程分開(kāi)吗跋。
建造者模式最大的好處就是使得構(gòu)建過(guò)程和表現(xiàn)分離侧戴,因此若需要改變一個(gè)產(chǎn)品的表現(xiàn),只需重新定義一個(gè)具體的建造者就可以了跌宛。舉個(gè)例子酗宋,我們將車(chē)的組裝過(guò)程獨(dú)立處來(lái),用這個(gè)組裝過(guò)程可以組裝出寶馬疆拘、奔馳或者其他車(chē)型蜕猫,如果要組裝新的車(chē)型,我們只需要重新定義一個(gè)具體的構(gòu)造者(用于產(chǎn)品表現(xiàn)的類(lèi))就可以了哎迄。
2. 情景設(shè)置
在軟件系統(tǒng)中丹锹,有時(shí)候會(huì)遇到一個(gè)復(fù)雜對(duì)象(比如上面例子中的汽車(chē))的創(chuàng)建,它通常由幾個(gè)部分的子對(duì)象采用一定的算法(過(guò)程)構(gòu)成芬失;由于需求的變化楣黍,這個(gè)復(fù)雜對(duì)象的各個(gè)部分經(jīng)常面臨著劇烈的變化(比如上面例子中,各種車(chē)型用的車(chē)門(mén)棱烂、方向盤(pán)租漂、發(fā)動(dòng)機(jī)等,是不一樣的),但是將各個(gè)部分組合在一起的算法(過(guò)程)時(shí)相對(duì)穩(wěn)定的哩治。
建造者模式就是在這樣的需求下誕生的秃踩,它封裝了變化點(diǎn)(組成部分),使得同樣的構(gòu)建過(guò)程可以創(chuàng)建不同的表現(xiàn)业筏。建造者模式結(jié)構(gòu)圖如圖2-1所示:
從結(jié)構(gòu)圖可以看到憔杨,生成器模式有兩個(gè)重要的角色:Director(指導(dǎo)者)和Builder(建造者)。Director知道Builder應(yīng)該建造什么(建造的過(guò)程)蒜胖,Builder知道如何建造(表現(xiàn))消别。在Director類(lèi)中定義了一個(gè)construct方法,指導(dǎo)具體的建造者ConcreteBuilder的對(duì)象去buildPart台谢。Builder是一個(gè)抽象接口(協(xié)議)寻狂,該協(xié)議中包含建造各個(gè)部分的方法(buildPart),用來(lái)構(gòu)建實(shí)際的產(chǎn)品Product朋沮,另外還有一個(gè)getResult方法蛇券,用來(lái)向客戶(hù)端返回構(gòu)建完成的Product。
這樣說(shuō)不知道大家是不是感覺(jué)很抽象樊拓?那咱們用一個(gè)生活的例子來(lái)通俗點(diǎn)說(shuō)纠亚。比如現(xiàn)在我要在老家修一個(gè)房子,首先我不知道怎么修房子(砌墻筋夏,缺建造者)菜枷,然后我也不知道怎么設(shè)計(jì)(修幾個(gè)房間,房間的布局叁丧,房間的窗戶(hù)怎么設(shè)計(jì)等等,缺指導(dǎo)者)岳瞭,于是我找來(lái)一幫民工(建造者)拥娄,他們會(huì)砌墻;另外我還得找設(shè)計(jì)師(指導(dǎo)者)瞳筏,他知道怎么設(shè)計(jì)稚瘾;最后,我還要確保民工(建造者)聽(tīng)設(shè)計(jì)師(指導(dǎo)者)的指導(dǎo)姚炕,哪里需要砌一堵墻摊欠,哪里需要安裝窗戶(hù)等等,這樣民工(建造者)就開(kāi)始蓋房子柱宦,在這個(gè)建造過(guò)程中些椒,設(shè)計(jì)師(指導(dǎo)者)只負(fù)責(zé)設(shè)計(jì)和下達(dá)命令。房子建成功后掸刊,民工(建造者)向我交房免糕。說(shuō)白了,就是Director(指導(dǎo)者)負(fù)責(zé)把控宏觀方面(過(guò)程),Builder(建造者)負(fù)責(zé)把控微觀方面(表現(xiàn)) 石窑。
3. 代碼實(shí)現(xiàn)
(1)Product
@interface Product : NSObject
{
NSMutableArray *arrParts;
}
- (void)addPart:(NSString *)part; // 添加產(chǎn)品的各個(gè)部分
- (void)show; // 展示產(chǎn)品
@end
@implementation Product
- (instancetype)init
{
if (self = [super init]) {
arrParts = [NSMutableArray array];
}
return self;
}
- (void)addPart:(NSString *)part
{
[arrParts addObject:part];
}
- (void)show
{
for (NSString *strPart in arrParts)
{
NSLog(@"%@",strPart);
}
}
@end
(2)Builder
@class Product;
@protocol Builder <NSObject>
- (void)addPartOne;
- (void)addPartTwo;
- (Product *)getResult;
@end
(3)Director
@interface Director : NSObject
- (void)construct:(id<Builder>)builder;
@end
@implementation Director
- (void)construct:(id<Builder>)builder
{
[builder addPartOne];
[builder addPartTwo];
}
@end
(4)ConcreteBuilder
@interface ConcreteBuilder : NSObject<Builder>
{
Product *product;
}
@end
@implementation ConcreteBuilder
- (instancetype)init
{
if (self = [super init]) {
product = [[Product alloc] init];
}
return self;
}
- (void)addPartOne
{
[product addPart:@"part one"];
}
- (void)addPartTwo
{
[product addPart:@"part two"];
}
- (Product *)getResult
{
return product;
}
@end
(5)客戶(hù)端調(diào)用
Director *director = [[Director alloc] init];
id<Builder> builder = [[ConcreteBuilder alloc] init];
[director construct:builder];
Product *product = [builder getResult];
[product show];
建造者模式常用于如下情形:
a. 需要?jiǎng)?chuàng)建涉及各種部件的復(fù)雜對(duì)象牌芋。創(chuàng)建對(duì)象的算法應(yīng)該獨(dú)立于部件的裝配方式。
b. 構(gòu)建過(guò)程需要以不同的方式構(gòu)建對(duì)象松逊。