iOS 設(shè)計(jì)模式之六(建造者模式)

一、概念

1、建造者模式的動(dòng)機(jī)

? 沒有人買車會(huì)只買一個(gè)輪胎或者方向盤抵乓,大家買的都是一輛包含輪胎、方向盤和發(fā)動(dòng)機(jī)等多個(gè)部件的完整汽車。如何將這些部件組裝成一輛完整的汽車并返回給用戶灾炭,這是建造者模式需要解決的問題茎芋。

2、建造者模式的定義

? 建造者模式(Builder Pattern):將一個(gè)復(fù)雜對(duì)象的構(gòu)建與它的表示分離蜈出,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示田弥。建造者模式是一種對(duì)象創(chuàng)建型模式。

? 建造者模式又稱為生成器模式铡原,它是一種較為復(fù)雜偷厦、使用頻率也相對(duì)較低的創(chuàng)建型模式。建造者模式為客戶端返回的不是一個(gè)簡(jiǎn)單的產(chǎn)品燕刻,而是一個(gè)由多個(gè)部件組成的復(fù)雜產(chǎn)品只泼。

3、建造者模式的4個(gè)角色

1)Builder(抽象建造者):它為創(chuàng)建一個(gè)產(chǎn)品Product對(duì)象的各個(gè)部件指定抽象接口卵洗,在該接口中一般聲明兩類方法请唱,一類方法是buildPartX(),它們用于創(chuàng)建復(fù)雜對(duì)象的各個(gè)部件过蹂;另一類方法是getResult()十绑,它們用于返回復(fù)雜對(duì)象。Builder既可以是抽象類酷勺,也可以是接口本橙。

2)ConcreteBuilder(具體建造者):它實(shí)現(xiàn)了Builder接口,實(shí)現(xiàn)各個(gè)部件的具體構(gòu)造和裝配方法鸥印,定義并明確它所創(chuàng)建的復(fù)雜對(duì)象勋功,也可以提供一個(gè)方法返回創(chuàng)建好的復(fù)雜產(chǎn)品對(duì)象。

3)Product(產(chǎn)品角色):它是被構(gòu)建的復(fù)雜對(duì)象库说,包含多個(gè)組成部件,具體建造者創(chuàng)建該產(chǎn)品的內(nèi)部表示并定義它的裝配過程片择。

4)Director(指揮者):指揮者又稱為導(dǎo)演類潜的,它負(fù)責(zé)安排復(fù)雜對(duì)象的建造次序,指揮者與抽象建造者之間存在關(guān)聯(lián)關(guān)系字管,可以在其construct()建造方法中調(diào)用建造者對(duì)象的部件構(gòu)造與裝配方法啰挪,完成復(fù)雜對(duì)象的建造。

4嘲叔、建造者模式與抽象工廠模式的區(qū)別

? 建造者模式與抽象工廠模式有點(diǎn)相似亡呵,但是建造者模式返回一個(gè)完整的復(fù)雜產(chǎn)品,而抽象工廠模式返回一系列相關(guān)的產(chǎn)品硫戈。在抽象工廠模式中锰什,客戶端通過選擇具體工廠來生成所需對(duì)象,而在建造者模式中,客戶端通過指定具體建造者類型并指導(dǎo)Director類如何去生成對(duì)象汁胆,側(cè)重于一步步構(gòu)造一個(gè)復(fù)雜對(duì)象梭姓,然后將結(jié)果返回。如果將抽象工廠模式看成一個(gè)汽車配件生產(chǎn)廠嫩码,生成不同類型的汽車配件誉尖,那么建造者模式就是一個(gè)汽車組裝廠,通過對(duì)配件進(jìn)行組裝返回一輛完整的汽車铸题。

5铡恕、結(jié)構(gòu)圖
建造者模式

二、示例

1)首先創(chuàng)建一個(gè)Phone類丢间,是產(chǎn)品角色没咙;

2)然后創(chuàng)建一個(gè)PhoneBuilder協(xié)議,是抽象建造者千劈,是個(gè)接口祭刚;

3)然后創(chuàng)建HuaWeiBuilder類和IphoneBuilder類,兩個(gè)類都遵循PhoneBuilder協(xié)議墙牌,實(shí)現(xiàn)協(xié)議的接口涡驮,是具體建造者;

4)最后創(chuàng)建PhoneDirector類喜滨,是指揮者捉捅。

具體代碼如下:

Phone類:

@interface Phone : NSObject
@property(nonatomic, copy) NSString *cpu;
@property(nonatomic, copy) NSString *screen;
@property(nonatomic, copy) NSString *camera;
@property(nonatomic, copy) NSString *system;
@end

@implementation Phone
@end

PhoneBuilder協(xié)議:

@protocol PhoneBuilder <NSObject>
@property(nonatomic, strong) Phone *phone;
- (void)buildCPU;
- (void)buildScreen;
- (void)buildCamera;
- (void)buildSystem;
@end

typedef id<PhoneBuilder> PhoneBuilder; //重新命名類型,方便后面使用

HuaWeiBuilder類:

@interface HuaWeiBuilder : NSObject<PhoneBuilder>
@end

@implementation HuaWeiBuilder
@synthesize phone = _phone;

- (instancetype)init
{
    self = [super init];
    if (self) {
        _phone = [Phone new];
    }
    return self;
}

- (void)buildCPU {
    _phone.cpu = @"麒麟處理器";
}

- (void)buildScreen {
    _phone.screen = @"京東方屏幕";
}

- (void)buildCamera {
    _phone.camera = @"萊卡攝像頭";
}

- (void)buildSystem {
    _phone.system = @"安卓系統(tǒng)";
}
@end

IphoneBuilder類:

@interface IphoneBuilder : NSObject<PhoneBuilder>
@end

@implementation IphoneBuilder
@synthesize phone = _phone;

- (instancetype)init
{
    self = [super init];
    if (self) {
        _phone = [Phone new];
    }
    return self;
}

- (void)buildCPU {
    _phone.cpu = @"A系列處理器";
}

- (void)buildScreen {
    _phone.screen = @"三星屏幕";
}

- (void)buildCamera {
    _phone.camera = @"Sony攝像頭";
}

- (void)buildSystem {
    _phone.system = @"iOS系統(tǒng)";
}
@end

PhoneDirector類:

@interface PhoneDirector : NSObject
- (Phone *)constructWithBuilder:(PhoneBuilder)builder;
@end

@implementation PhoneDirector
- (Phone *)constructWithBuilder:(PhoneBuilder)builder {
    [builder buildCPU];
    [builder buildScreen];
    [builder buildCamera];
    [builder buildSystem];
    return builder.phone;
}
@end

運(yùn)行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    PhoneDirector *director = [PhoneDirector new];
    HuaWeiBuilder *huaWeiBuilder = [HuaWeiBuilder new];
    IphoneBuilder *iPhoneBuilder = [IphoneBuilder new];
    
    Phone *huaWeiPhone = [director constructWithBuilder:huaWeiBuilder];
    Phone *iphone = [director constructWithBuilder:iPhoneBuilder];
    NSLog(@"HuaWeiPhone:cpu = %@, screen = %@, camera = %@, system = %@", huaWeiPhone.cpu, huaWeiPhone.screen, huaWeiPhone.camera, huaWeiPhone.system);
    NSLog(@"iPhone:cpu = %@, screen = %@, camera = %@, system = %@", iphone.cpu, iphone.screen, iphone.camera, iphone.system);
}

打印結(jié)果:

HuaWeiPhone:cpu = 麒麟處理器, screen = 京東方屏幕, camera = 萊卡攝像頭, system = 安卓系統(tǒng)
iPhone:cpu = A系列處理器, screen = 三星屏幕, camera = Sony攝像頭, system = iOS系統(tǒng)

三虽风、總結(jié)

? 建造者模式的核心在于如何一步步構(gòu)建一個(gè)包含多個(gè)組成部件的完整對(duì)象棒口,使用相同的構(gòu)建過程構(gòu)建不同的產(chǎn)品,在軟件開發(fā)中辜膝,如果我們需要?jiǎng)?chuàng)建復(fù)雜對(duì)象并希望系統(tǒng)具備很好的靈活性和可擴(kuò)展性可以考慮使用建造者模式无牵。

? 在有些情況下,為了簡(jiǎn)化系統(tǒng)結(jié)構(gòu)厂抖,可以將Director和抽象建造者Builder進(jìn)行合并茎毁,在Builder中提供逐步構(gòu)建復(fù)雜產(chǎn)品對(duì)象的construct()方法。

1忱辅、優(yōu)點(diǎn)

1七蜘、在建造者模式中,客戶端不必知道產(chǎn)品內(nèi)部組成的細(xì)節(jié)墙懂,將產(chǎn)品本身與產(chǎn)品的創(chuàng)建過程解耦橡卤,使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品對(duì)象。

2损搬、每一個(gè)具體建造者都相對(duì)獨(dú)立碧库,而與其他的具體建造者無(wú)關(guān)柜与,因此可以很方便地替換具體建造者或增加新的具體建造者,用戶使用不同的具體建造者即可得到不同的產(chǎn)品對(duì)象谈为。由于指揮者類針對(duì)抽象建造者編程旅挤,增加新的具體建造者無(wú)須修改原有類庫(kù)的代碼,系統(tǒng)擴(kuò)展方便伞鲫,符合“開閉原則”粘茄。

3、可以更加精細(xì)地控制產(chǎn)品的創(chuàng)建過程秕脓。將復(fù)雜產(chǎn)品的創(chuàng)建步驟分解在不同的方法中柒瓣,使得創(chuàng)建過程更加清晰,也更方便使用程序來控制創(chuàng)建過程吠架。

2芙贫、缺點(diǎn)

1、建造者模式所創(chuàng)建的產(chǎn)品一般具有較多的共同點(diǎn)傍药,其組成部分相似磺平,如果產(chǎn)品之間的差異性很大,例如很多組成部分都不相同拐辽,不適合使用建造者模式拣挪,因此其使用范圍受到一定的限制。

2俱诸、如果產(chǎn)品的內(nèi)部變化復(fù)雜菠劝,可能會(huì)導(dǎo)致需要定義很多具體建造者類來實(shí)現(xiàn)這種變化,導(dǎo)致系統(tǒng)變得很龐大睁搭,增加系統(tǒng)的理解難度和運(yùn)行成本赶诊。

3、適用場(chǎng)景

1园骆、需要生成的產(chǎn)品對(duì)象有復(fù)雜的內(nèi)部結(jié)構(gòu)舔痪,這些產(chǎn)品對(duì)象通常包含多個(gè)成員屬性。

2遇伞、需要生成的產(chǎn)品對(duì)象的屬性相互依賴辙喂,需要指定其生成順序。

3鸠珠、 對(duì)象的創(chuàng)建過程獨(dú)立于創(chuàng)建該對(duì)象的類。在建造者模式中通過引入了指揮者類秋麸,將創(chuàng)建過程封裝在指揮者類中渐排,而不在建造者類和客戶類中。

4灸蟆、隔離復(fù)雜對(duì)象的創(chuàng)建和使用驯耻,并使得相同的創(chuàng)建過程可以創(chuàng)建不同的產(chǎn)品。

4、iOS應(yīng)用舉例

? 比如SDWebImage的SDWebImageDownloader和SDWebImageDownloaderOperation就是director和builder之間的關(guān)系可缚。前者不負(fù)責(zé)具體的下載操作霎迫,只負(fù)責(zé)管理builder,builder負(fù)責(zé)圖片的具體下載帘靡。

Demo地址:iOS-Design-Patterns

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末知给,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子描姚,更是在濱河造成了極大的恐慌涩赢,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件轩勘,死亡現(xiàn)場(chǎng)離奇詭異筒扒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)绊寻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門花墩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人澄步,你說我怎么就攤上這事冰蘑。” “怎么了驮俗?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵懂缕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我王凑,道長(zhǎng)搪柑,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任索烹,我火速辦了婚禮工碾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘百姓。我一直安慰自己渊额,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布垒拢。 她就那樣靜靜地躺著旬迹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪求类。 梳的紋絲不亂的頭發(fā)上奔垦,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音尸疆,去河邊找鬼椿猎。 笑死惶岭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的犯眠。 我是一名探鬼主播按灶,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼筐咧!你這毒婦竟也來了鸯旁?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗜浮,失蹤者是張志新(化名)和其女友劉穎羡亩,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體危融,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畏铆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吉殃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辞居。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蛋勺,靈堂內(nèi)的尸體忽然破棺而出瓦灶,到底是詐尸還是另有隱情,我是刑警寧澤抱完,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布贼陶,位于F島的核電站,受9級(jí)特大地震影響巧娱,放射性物質(zhì)發(fā)生泄漏碉怔。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一禁添、第九天 我趴在偏房一處隱蔽的房頂上張望撮胧。 院中可真熱鬧,春花似錦老翘、人聲如沸芹啥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)墓怀。三九已至,卻和暖如春卫键,著一層夾襖步出監(jiān)牢的瞬間捺疼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工永罚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啤呼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓呢袱,卻偏偏與公主長(zhǎng)得像官扣,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子羞福,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容