建造者模式
建造者模式(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 類腻扇,帶有 Item 的 ArrayList 和一個通過結(jié)合 Item 來創(chuàng)建不同類型的 Meal 對象的 MealBuilder债热。BuilderPatternDemo,我們的演示類使用 MealBuilder 來創(chuàng)建一個 Meal幼苛。
步驟 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