天天看點

IOS設計模式淺析之建造者模式(Builder)

定義                                                                                                        

  "将一個複雜對象的建構與它的表現分離,使得同樣的建構過程可以建立不同的表現"。

  • 最初的定義出現于《設計模式》(Addison-Wesley,1994)。

  看這個概念,可能感覺很是抽象,能看懂但是不知道有什麼用。我們打一個比方來了解上面的定義。打比方之前,咱們先來聊聊這個設計模式是幹什麼用的?我們為什麼要用這個模式呢?建造者模式負責将建構複雜對象的過程和它的部件解耦,也就是過程和部件的解耦。比如說汽車,是一個很複雜的對象,它有很多的部件,車輪、發動機、座椅、車門、油箱等等;它的組裝過程也很複雜(需要專業人士按步驟進行裝配),建造者模式就是為了将部件群組裝過程分開的。同樣的,我們使用的計算機也一樣,有很多的部件,組裝過程也很複雜(當然,對于我們這樣的專業人士可能感覺不複雜)。建造者模式最大的好處就是使得建構過程和表現分離,是以若需要改變一個産品的表現,隻需要重新定義一個具體的建造者就可以了(這句話了解起來有點難度,還是拿車來打比方,我們将車的組裝過程獨立出來,用這個組裝過程,我們即可以組裝寶馬車,也可以組裝奔馳車,或者其他的車型,我們隻需要重新定義一個具體的建造者(用于産品表現的類)就可以了)。

動機                                                                                                        

  在軟體系統中,有時候會遇到一個複雜對象(比如說上面例子中的汽車)的建立,它通常由幾個部分的子對象采用一定的算法(過程)構成;由于需求的變化,這個複雜對象的各個部分經常面臨着劇烈的變化(比如上面例子中,各種車型用的車門、方向盤、發動機等,是不一樣的),但是将各個部分組合在一起的算法(過程)是相對穩定的。

  建造者模式就是在這樣的需求下誕生的,它封裝了變化點(組成部分),使得同樣的建構過程可以建立不同的表現。

結構圖                                                                                                    

IOS設計模式淺析之建造者模式(Builder)

  從結構圖可以看到,生成器模式有兩個重要的角色:Director(指導者)和Builder(建造者)。Director知道Builder應該建造什麼(建造的過程),Builder知道如何建造(表現)。在Director類中定義了一個construct方法,指導具體的建造者ConcreteBuilder的對象去buildPart。Builder是一個抽象接口(協定),該協定中包含建造各個部分的方法(buildPart),用來建構實際的産品Product,另外還有一個getResult方法,用來向用戶端傳回建構完成的Product。

  這樣說不知道大家是不是感覺很抽象?那咱們用一個生活的例子來通俗點說。比如現在我要在老家修一個房子,首先我不知道怎麼修房子(砌牆,缺建造者),然後我也不知道怎麼設計(修幾個房間,房間的布局,房間的窗戶怎麼設計等等,缺指導者),于是我找來一幫民工(建造者),他們會砌牆;另外我還得找設計師(指導者),他知道怎麼設計;最後,我還要確定民工(建造者)聽設計師(指導者)的指導,哪裡需要砌一堵牆,哪裡需要安裝窗戶等等,這樣民工(建造者)就開始蓋房子,在這個建造過程中,設計師(指導者)隻負責設計和下達指令。房子建成功後,民工(建造者)向我交房。說白了,就是Director(指導者)負責把控宏觀方面(過程),Builder(建造者)負責把控微觀方面(表現) 。

  下面咱們還是通過代碼來說明這個結構圖。

建造者模式的代碼                                                                                     

  Product.m(部分代碼):

1 - (id)init
 2 
 3 {
 4 
 5     self = [superinit];
 6 
 7     
 8 
 9     if (self)
10 
11     {
12 
13         arrParts = [NSMutableArrayarray];
14 
15     }
16 
17     
18 
19     returnself;
20 
21 }
22 
23  
24 
25 - (void)addPart:(NSString *)part
26 
27 {
28 
29     [arrPartsaddObject:part];
30 
31 }
32 
33  
34 
35 - (void)show
36 
37 {
38 
39     for (NSString *strPart inarrParts)
40 
41     {
42 
43         NSLog(@"%@",strPart);
44 
45     }
46 
47 }      

  Builder.h(部分代碼):

1 @classProduct;
 2 
 3 @protocol Builder <NSObject>
 4 
 5  
 6 
 7 - (void)addPartOne;
 8 
 9 - (void)addPartTwo;
10 
11 - (Product *)getResult;
12 
13  
14 
15 @end      

  ConcreteBuilder.m(部分代碼):

1 - (id)init
 2 
 3 {
 4 
 5     self = [superinit];
 6 
 7     
 8 
 9     if (self)
10 
11     {
12 
13         product = [[Productalloc] init];
14 
15     }
16 
17     
18 
19     returnself;
20 
21 }
22 
23  
24 
25 - (void)addPartOne
26 
27 {
28 
29     [productaddPart:@"part one"];
30 
31 }
32 
33  
34 
35 - (void)addPartTwo
36 
37 {
38 
39     [productaddPart:@"part two"];
40 
41 }
42 
43  
44 
45 - (Product *)getResult
46 
47 {
48 
49     returnproduct;
50 
51 }
52 
53 Director.m(部分代碼):
54 
55 - (void)construct:(id<Builder>)builder
56 
57 {
58 
59     [builder addPartOne];
60 
61     [builder addPartTwo];
62 
63 }      

  用戶端調用代碼:

1         Director *director = [[Directoralloc] init];
 2 
 3         id<Builder> builder = [[ConcreteBuilderalloc] init];
 4 
 5         
 6 
 7         [director construct:builder];
 8 
 9         Product *product = [builder getResult];
10 
11         [product show];
12 
13         
14 
15         [builder release];
16 
17         [director release];      

何時使用建造者模式                                                                                 

  建造者模式常用于如下情形:

  • 需要建立涉及各種部件的複雜對象。建立對象的算法應該獨立于部件的裝配方式。
  • 建構過程需要以不同的方式建構對象。

  源碼下載下傳  傳回目錄

循自然之道,撫浮躁之心