設(shè)計模式之建造者模式(4)

建造者模式

建造者模式(Builder Pattern)使用多個簡單的對象一步一步構(gòu)建成一個復(fù)雜的對象。這種類型的設(shè)計模式屬于創(chuàng)建型模式拾给,它提供了一種創(chuàng)建對象的最佳方式也殖。

一個 Builder 類會一步一步構(gòu)造最終的對象寇漫。該 Builder 類是獨立于其他對象的尿扯。

介紹

意圖:將一個復(fù)雜的構(gòu)建與其表示相分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表示崖蜜。

主要解決:主要解決在軟件系統(tǒng)中浊仆,有時候面臨著"一個復(fù)雜對象"的創(chuàng)建工作烙肺,其通常由各個部分的子對象用一定的算法構(gòu)成;由于需求的變化氧卧,這個復(fù)雜對象的各個部分經(jīng)常面臨著劇烈的變化桃笙,但是將它們組合在一起的算法卻相對穩(wěn)定。

何時使用:一些基本部件不會變沙绝,而其組合經(jīng)常變化的時候搏明。

如何解決:將變與不變分離開。

關(guān)鍵代碼:建造者:創(chuàng)建和提供實例闪檬,導(dǎo)演:管理建造出來的實例的依賴關(guān)系星著。

應(yīng)用實例: 1、去肯德基粗悯,漢堡虚循、可樂、薯條样傍、炸雞翅等是不變的横缔,而其組合是經(jīng)常變化的,生成出所謂的"套餐"衫哥。 2茎刚、JAVA 中的 StringBuilder。

優(yōu)點: 1撤逢、建造者獨立膛锭,易擴展。 2蚊荣、便于控制細節(jié)風險初狰。

缺點: 1、產(chǎn)品必須有共同點互例,范圍有限制奢入。 2、如內(nèi)部變化復(fù)雜敲霍,會有很多的建造類俊马。

使用場景: 1丁存、需要生成的對象具有復(fù)雜的內(nèi)部結(jié)構(gòu)肩杈。 2、需要生成的對象內(nèi)部屬性本身相互依賴解寝。

注意事項:與工廠模式的區(qū)別是:建造者模式更加關(guān)注與零件裝配的順序扩然。

實現(xiàn)

我們假設(shè)一個快餐店的商業(yè)案例,其中聋伦,一個典型的套餐可以是一個漢堡(Burger)和一杯冷飲(Cold drink)夫偶。漢堡(Burger)可以是素食漢堡(Veg Burger)或雞肉漢堡(Chicken Burger)界睁,它們是包在紙盒中。冷飲(Cold drink)可以是可口可樂(coke)或百事可樂(pepsi)兵拢,它們是裝在瓶子中翻斟。

我們將創(chuàng)建一個表示食物條目(比如漢堡和冷飲)的 Item 接口和實現(xiàn) Item 接口的實體類,以及一個表示食物包裝的 Packing 接口和實現(xiàn) Packing接口的實體類说铃,漢堡是包在紙盒中访惜,冷飲是裝在瓶子中。

然后我們創(chuàng)建一個 Meal 類腻扇,帶有 ItemArrayList 和一個通過結(jié)合 Item 來創(chuàng)建不同類型的 Meal 對象的 MealBuilder债热。BuilderPatternDemo,我們的演示類使用 MealBuilder 來創(chuàng)建一個 Meal幼苛。

建造者模式的 UML 圖

步驟 1
創(chuàng)建一個表示食物條目和食物包裝的接口窒篱。

@interface Packing : NSObject
- (NSString *)pack;
@end
@interface Item : NSObject
- (NSString*)name;
- (Packing*)packing;
- (float)price;
@end

步驟 2
創(chuàng)建實現(xiàn) Packing 接口的實體類。

@interface Wrapper : Packing
- (NSString *)pack;
@end
@interface Bottle : Packing
- (NSString *)pack;
@end

@implementation Wrapper

- (NSString *)pack{
    return @"Wrapper";
}

@end
@implementation Bottle

- (NSString *)pack{
    return @"Bottle";
}

@end

步驟 3
創(chuàng)建實現(xiàn) Item 接口的抽象類舶沿,該類提供了默認的功能墙杯。

@interface Burger : Item
- (Packing *)packing;
- (float)price;
- (NSString *)name;
@end

@interface ColdDrink : Item
- (Packing *)packing;
- (float)price;
- (NSString *)name;
@end

@implementation Burger

- (Packing*)packing{
    return [Wrapper new];
}
- (float)price{
    return 0.0f;
}
- (nonnull NSString *)name {
    return @"";
}
@end
@implementation ColdDrink

- (Packing*)packing{
    return [Bottle new];
}
- (float)price{
    return 0.0f;
}

- (nonnull NSString *)name {
    return @"";
}

@end

步驟 4
創(chuàng)建擴展了 Burger 和 ColdDrink 的實體類。

@interface VegBurger : Burger
- (float)price;
- (NSString *)name;
@end

@interface ChickenBurger : Burger
- (float)price;
- (NSString *)name;
@end

@interface Coke : ColdDrink
- (float)price;
- (NSString *)name;

@end

@interface Pepsi : ColdDrink
- (float)price;
- (NSString *)name;

@end

@implementation VegBurger

- (float)price{
    return 25.0f;
}
- (NSString *)name{
    return @"Veg Burger";
}

@end


@implementation ChickenBurger

- (float)price{
    return 50.0f;
}
- (NSString *)name{
    return @"Chicken Burger";
}
@end

@implementation Pepsi

-(float)price{
    return 35.0f;
}
- (NSString *)name{
    return @"Pepsi";
}
@end
@implementation Coke

-(float)price{
    return 30.0f;
}
- (NSString *)name{
    return @"Coke";
}
@end

步驟 5
創(chuàng)建一個 Meal 類括荡,帶有上面定義的 Item 對象霍转。

@interface Meal : NSObject

- (void)addItem:(Item *)item;
- (float)getCost;
- (void)showItems;
@end

@interface Meal ()
@property (nonatomic,strong) NSMutableArray *list;
@end
@implementation Meal
- (NSMutableArray *)list{
    if (_list == nil) {
        _list=[NSMutableArray array];
    }
    return _list;
}
- (void)addItem:(Item *)item{
    if ([item isKindOfClass:[item class]]) {
        [_list addObject:item];
    }
}
- (float)getCost{
    float  count = 0.f;
    for (Item *it in self.list) {
        if ([it isKindOfClass:[Item class]]) {
            count += it.price;
        }
    }
    return count;
}
- (void)showItems{
    for (Item *it in self.list) {
        if ([it isKindOfClass:[Item class]]) {
            NSLog(@"Item:%@",it.name);
            NSLog(@"Packing:%@",it.packing.pack);
            NSLog(@"price:%f",it.price);
        }
    }
}
@end

步驟 6
創(chuàng)建一個 MealBuilder 類,實際的 builder 類負責創(chuàng)建 Meal 對象一汽。

@interface MealBuild : NSObject

- (Meal*)prepareVeMeal;

- (Meal*)prepareNoneVeMeal;

@end

@implementation MealBuild

-(Meal *)prepareNoneVeMeal{
    Meal *ml = [Meal new];
    [ml addItem:[ChickenBurger new]];
    [ml addItem:[Pepsi new]];
    return ml;
}
- (Meal *)prepareVeMeal{
    Meal *ml = [Meal new];
    [ml addItem:[VegBurger new]];
    [ml addItem:[Coke new]];
    return ml;
}

@end

步驟 7
BuiderPatternDemo 使用 MealBuider 來演示建造者模式(Builder Pattern)避消。

 MealBuild *mlb=[MealBuild new];
    Meal *vemeal = [mlb prepareVeMeal];
    NSLog(@"Veg Meal");
    [vemeal showItems];
    NSLog(@"totalCost:%f",vemeal .getCost);
    
    Meal *ml =[mlb prepareNoneVeMeal];
    NSLog(@"NoneVeMeal");
    [ml showItems];
    NSLog(@"totalCost:%f",ml.getCost);

步驟 8
執(zhí)行程序,輸出結(jié)果:

Veg Meal
Item : Veg Burger, Packing : Wrapper, Price : 25.0
Item : Coke, Packing : Bottle, Price : 30.0
Total Cost: 55.0


Non-Veg Meal
Item : Chicken Burger, Packing : Wrapper, Price : 50.5
Item : Pepsi, Packing : Bottle, Price : 35.0
Total Cost: 85.5
建造者模式中心思路是如何抽象物品召夹,抽出來共同的屬性成一個基類岩喷,只聲明一些接口而不實現(xiàn),又一個基類衍生出來具體的分裂监憎,有具體的分類再到具體的物品纱意,多個物品則組裝成了一個我們需要的產(chǎn)品。

參考資料
runoob

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鲸阔,一起剝皮案震驚了整個濱河市偷霉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌褐筛,老刑警劉巖类少,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異渔扎,居然都是意外死亡硫狞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來残吩,“玉大人财忽,你說我怎么就攤上這事∑辏” “怎么了即彪?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長活尊。 經(jīng)常有香客問我祖凫,道長,這世上最難降的妖魔是什么酬凳? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任惠况,我火速辦了婚禮,結(jié)果婚禮上宁仔,老公的妹妹穿的比我還像新娘稠屠。我一直安慰自己,他們只是感情好翎苫,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布权埠。 她就那樣靜靜地躺著,像睡著了一般煎谍。 火紅的嫁衣襯著肌膚如雪攘蔽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天呐粘,我揣著相機與錄音满俗,去河邊找鬼。 笑死作岖,一個胖子當著我的面吹牛唆垃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播痘儡,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辕万,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了沉删?” 一聲冷哼從身側(cè)響起渐尿,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矾瑰,沒想到半個月后砖茸,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡脯倚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年渔彰,在試婚紗的時候發(fā)現(xiàn)自己被綠了嵌屎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片订讼。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡饰及,死狀恐怖锅知,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情再沧,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布尊残,位于F島的核電站炒瘸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏寝衫。R本人自食惡果不足惜顷扩,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望慰毅。 院中可真熱鬧隘截,春花似錦、人聲如沸汹胃。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽着饥。三九已至犀农,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間宰掉,已是汗流浹背呵哨。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留轨奄,地道東北人仇穗。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像戚绕,于是被迫代替她去往敵國和親纹坐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355