
iOS設(shè)計(jì)模式之美-工廠模式
iOS設(shè)計(jì)模式之美-抽象工廠模式
iOS設(shè)計(jì)模式之美-生成器模式
iOS設(shè)計(jì)模式之美-適配器模式
1.何為生成器模式
將一個(gè)復(fù)雜對象的構(gòu)建與它的表現(xiàn)分離,使得同樣的構(gòu)建過程可以創(chuàng)建不同的表現(xiàn)
上面的表述可能有些抽象,我們用生活中的例子為大家說明下:
有時(shí)候我們雖然在同一家外賣店點(diǎn)的相同的商品,有可能體驗(yàn)會(huì)相差很大。
第一次,臥槽,這家店的蔥爆牛肉炒飯好好吃啊,老子下次還要點(diǎn)!!
第二次,臥槽,我點(diǎn)的蔥爆牛肉炒飯?jiān)趺礇]牛肉,牛肉哪里去了?。?br>
第三次,老子不信邪,再點(diǎn)一次蔥爆牛肉炒飯看看,臥槽,老板忘記放鹽了??!Boom.........
為什么同一家同一款商品而且還是同一個(gè)師傅做的,有時(shí)候差異性會(huì)那么大呢?這時(shí)我們再想想,你平時(shí)點(diǎn)的肯德基(這次不用金拱門做例子了,到時(shí)候你們還以為我收了廣告費(fèi)/(ㄒoㄒ)/~~)外賣會(huì)出現(xiàn)口味差異那么大的情況嗎?同學(xué)們可能會(huì)說,別人是專業(yè)的??!有一套整體規(guī)范的制作流程。沒錯(cuò),對于同樣一款商品在肯德基中的制作流程可能細(xì)節(jié)到了使用多少克配料,油炸的時(shí)長具體是幾分鐘,這些都是有嚴(yán)格的把控的。通過這個(gè)簡單的例子應(yīng)該能幫助我們對生成器模式中的對象構(gòu)建和表現(xiàn)分離這一思想有所啟發(fā)。
2.何時(shí)使用生成器模式
- 需要?jiǎng)?chuàng)建涉及各種部件的復(fù)雜對象。創(chuàng)建對象的算法應(yīng)該獨(dú)立于部分的裝配方式,常見例子是構(gòu)建組合對象。
- 構(gòu)建過程是穩(wěn)定可抽象的,而構(gòu)建對象所需的部件是可變動(dòng)的
3.生成器模式靜態(tài)類結(jié)構(gòu)圖

生成器模式由Director(指導(dǎo)者)、Builder(生成器)、Product(產(chǎn)品)三者構(gòu)成。
Director(漢堡制作流程):抽象對象構(gòu)建流程
Builder(漢堡制作師傅):抽象對象構(gòu)建部件方法
Product(漢堡):實(shí)際產(chǎn)品類
4.生成器模式時(shí)序圖

這里客戶端首先知悉并生成Director和ConcreteBuilder,將它們用于今后的協(xié)同工作。當(dāng)Client發(fā)送construct消息給Director時(shí),該方法告訴Director要構(gòu)建什么。Director執(zhí)行內(nèi)部構(gòu)建流程,這里Director和ConcreteBuilder是一個(gè)聚合關(guān)系。構(gòu)建成功后客戶端通過getResult方法從ConcreteBuilder中直接取回產(chǎn)品。
這里可能有人要問,為什么要讓Client知悉Director,直接用construct方法返回構(gòu)建的產(chǎn)品即可。沒錯(cuò),如果消除ConcreteBuilder那么跟普通的工廠模式十分相似了。這里也就是生成器模式和工廠模式的區(qū)分點(diǎn),前面也有提到過該模式的核心點(diǎn)就是對可復(fù)用的構(gòu)建流程和構(gòu)建組件進(jìn)行抽象化,這樣便于以后模塊的復(fù)用。同樣的構(gòu)建流程,替換不同的ConcreteBuilder即可生成其他相似的產(chǎn)品,也保障了同類型性產(chǎn)品制作的準(zhǔn)確性。
5.案例
代碼以上述肯德基生產(chǎn)漢堡為基準(zhǔn):
WCQDirector.h
#import <Foundation/Foundation.h>
#import "WCQBuilder.h"
@interface WCQDirector : NSObject
@property (nonatomic, strong) id<WCQBuilder> concreteBuilder;
- (void)construct;
@end
WCQDirector.m
#import "WCQDirector.h"
@implementation WCQDirector
- (void)construct {
[_concreteBuilder addBread];
[_concreteBuilder addSauce];
[_concreteBuilder addMeat];
}
@end
WCQBuilder.h
#import <Foundation/Foundation.h>
@protocol WCQBuilder <NSObject>
- (void)addBread; //添加面包
- (void)addSauce; //添加醬料
- (void)addMeat; //添加肉餅
@end
WCQConcreteBuilder.h
#import <Foundation/Foundation.h>
#import "WCQBuilder.h"
@interface WCQConcreteBuilder : NSObject<WCQBuilder>
- (id)getHamburger;
@end
WCQConcreteBuilder.m
#import "WCQConcreteBuilder.h"
#import "WCQHamburger.h"
@interface WCQConcreteBuilder ()
@property (nonatomic, strong) WCQHamburger *hamburger;
@end
@implementation WCQConcreteBuilder
- (instancetype)init {
if (self = [super init]) {
_hamburger = [[WCQHamburger alloc] init];
}
return self;
}
- (void)addBread {
_hamburger.bread = @"小麥面包";
}
- (void)addSauce {
_hamburger.sauce = @"芝士醬";
}
- (void)addMeat {
_hamburger.meat = @"牛肉餅";
}
-(id)getHamburger {
return _hamburger;
}
@end
WCQHamburger.h
#import <Foundation/Foundation.h>
@interface WCQHamburger : NSObject
@property (nonatomic, copy) NSString *bread;
@property (nonatomic, copy) NSString *sauce;
@property (nonatomic, copy) NSString *meat;
@end
客戶端調(diào)用示例:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
WCQConcreteBuilder *concreteBuilder = [[WCQConcreteBuilder alloc] init];
WCQDirector *director = [[WCQDirector alloc] init];
director.concreteBuilder = concreteBuilder;
[director construct];
WCQHamburger *hamburger = [concreteBuilder getHamburger];
}
從上述代碼示例可以看到,制作漢堡的流程已抽象到Director中,每次生成漢堡都將執(zhí)行該流程,這就避免了制作同種漢堡時(shí)可能造成的口味偏差問題(少放醬料等問題)。同時(shí)如果需要制作其他口味的漢堡只需替換不同的漢堡制作師傅(ConcreteBuilder)即可。
以上為本人個(gè)人理解與分享,如有錯(cuò)誤歡迎指出??
