1. 何為建造者模式
定義:將一個復雜對象的構建與它的表現(xiàn)分離,使得同樣的構建過程可以創(chuàng)建不同的表現(xiàn)。
建造者模式負責將構建復雜對象的過程和它的部件解耦,也就是過程和部件的解耦。比如說汽車,是一個很復雜的對象,它有很多的部件,車輪、發(fā)動機、座椅、車門、郵箱等等;它的組裝過程也很復雜(需要專業(yè)人士按照步驟進行裝配),建造者模式就是為了將部件和組裝過程分開。
建造者模式最大的好處就是使得構建過程和表現(xiàn)分離,因此若需要改變一個產(chǎn)品的表現(xiàn),只需重新定義一個具體的建造者就可以了。舉個例子,我們將車的組裝過程獨立處來,用這個組裝過程可以組裝出寶馬、奔馳或者其他車型,如果要組裝新的車型,我們只需要重新定義一個具體的構造者(用于產(chǎn)品表現(xiàn)的類)就可以了。
2. 情景設置
在軟件系統(tǒng)中,有時候會遇到一個復雜對象(比如上面例子中的汽車)的創(chuàng)建,它通常由幾個部分的子對象采用一定的算法(過程)構成;由于需求的變化,這個復雜對象的各個部分經(jīng)常面臨著劇烈的變化(比如上面例子中,各種車型用的車門、方向盤、發(fā)動機等,是不一樣的),但是將各個部分組合在一起的算法(過程)時相對穩(wěn)定的。
建造者模式就是在這樣的需求下誕生的,它封裝了變化點(組成部分),使得同樣的構建過程可以創(chuàng)建不同的表現(xiàn)。建造者模式結構圖如圖2-1所示:
從結構圖可以看到,生成器模式有兩個重要的角色:Director(指導者)和Builder(建造者)。Director知道Builder應該建造什么(建造的過程),Builder知道如何建造(表現(xiàn))。在Director類中定義了一個construct方法,指導具體的建造者ConcreteBuilder的對象去buildPart。Builder是一個抽象接口(協(xié)議),該協(xié)議中包含建造各個部分的方法(buildPart),用來構建實際的產(chǎn)品Product,另外還有一個getResult方法,用來向客戶端返回構建完成的Product。
這樣說不知道大家是不是感覺很抽象?那咱們用一個生活的例子來通俗點說。比如現(xiàn)在我要在老家修一個房子,首先我不知道怎么修房子(砌墻,缺建造者),然后我也不知道怎么設計(修幾個房間,房間的布局,房間的窗戶怎么設計等等,缺指導者),于是我找來一幫民工(建造者),他們會砌墻;另外我還得找設計師(指導者),他知道怎么設計;最后,我還要確保民工(建造者)聽設計師(指導者)的指導,哪里需要砌一堵墻,哪里需要安裝窗戶等等,這樣民工(建造者)就開始蓋房子,在這個建造過程中,設計師(指導者)只負責設計和下達命令。房子建成功后,民工(建造者)向我交房。說白了,就是Director(指導者)負責把控宏觀方面(過程),Builder(建造者)負責把控微觀方面(表現(xiàn)) 。
3. 代碼實現(xiàn)
(1)Product
@interface Product : NSObject
{
NSMutableArray *arrParts;
}
- (void)addPart:(NSString *)part; // 添加產(chǎn)品的各個部分
- (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)客戶端調用
Director *director = [[Director alloc] init];
id<Builder> builder = [[ConcreteBuilder alloc] init];
[director construct:builder];
Product *product = [builder getResult];
[product show];
建造者模式常用于如下情形:
a. 需要創(chuàng)建涉及各種部件的復雜對象。創(chuàng)建對象的算法應該獨立于部件的裝配方式。
b. 構建過程需要以不同的方式構建對象。