行為型模式
迭代器模式
模式動(dòng)機(jī)
針對(duì)不同的需要泊脐,可能還要以不同的方式遍歷整個(gè)聚合對(duì)象备蚓,但是我們并不希望在聚合對(duì)象的抽象層接口中充斥著各種不同遍歷的操作课蔬。
怎樣遍歷一個(gè)聚合對(duì)象,又不需要了解聚合對(duì)象的內(nèi)部結(jié)構(gòu)郊尝,還能夠提供多種不同的遍歷方式二跋,這就是迭代器模式的模式動(dòng)機(jī)。
模式定義
提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中的各個(gè)元素流昏,而又不暴露該對(duì)象的內(nèi)部表示扎即。
模式結(jié)構(gòu)
模板方法模式包含如下角色:
- Aggregate: 聚集抽象類
- ConcreteAggregate: 具體聚集類
- Iterator: 迭代抽象類
- ConcreteIterator: 具體迭代器類
時(shí)序圖
略
源碼
略
行為型
命令模式
模式動(dòng)機(jī)
在軟件設(shè)計(jì)中吞获,我們經(jīng)常需要向某些對(duì)象發(fā)送請(qǐng)求,但是并不知道請(qǐng)求的接收者是誰(shuí)谚鄙,也不知道被請(qǐng)求的操作是哪個(gè)各拷,我們只需在程序運(yùn)行時(shí)指定具體的請(qǐng)求接收者即可,此時(shí)闷营,可以使用命令模式來(lái)進(jìn)行設(shè)計(jì)烤黍,使得請(qǐng)求發(fā)送者與請(qǐng)求接收者消除彼此之間的耦合,讓對(duì)象之間的調(diào)用關(guān)系更加靈活傻盟。
命令模式可以對(duì)發(fā)送者和接收者完全解耦速蕊,發(fā)送者與接收者之間沒(méi)有直接引用關(guān)系,發(fā)送請(qǐng)求的對(duì)象只需要知道如何發(fā)送請(qǐng)求莫杈,而不必知道如何完成請(qǐng)求互例。這就是命令模式的模式動(dòng)機(jī)。
模式定義
命令模式(Command Pattern):將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象筝闹,從而使我們可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化;對(duì)請(qǐng)求排隊(duì)或者記錄請(qǐng)求日志腥光,以及支持可撤銷的操作关顷。命令模式是一種對(duì)象行為型模式,其別名為動(dòng)作(Action)模式或事務(wù)(Transaction)模式武福。
模式結(jié)構(gòu)
命令模式包含如下角色:
- Command: 抽象命令類
- ConcreteCommand: 具體命令類
- Invoker: 調(diào)用者
- Receiver: 接收者
-
Client:客戶類
命令模式類圖
時(shí)序圖
源碼
//使用示例
//waiter用于接收各種類型的order议双。waiter是請(qǐng)求接收者。
//接收不同customer產(chǎn)生的不同order捉片,并且都存入waiter這個(gè)接受者中,type表示不同類型的order平痰。
HCDWaiter *waiter = [[HCDWaiter alloc]init];
//顧客一
HCDCustomr *customer = [[HCDCustomr alloc]init];
HCDOrder *customerOrder1 = [customer pushOrderWithString:@"顧客一要十串羊肉" type:orderTypeMutton];
HCDOrder *customerOrder2 = [customer pushOrderWithString:@"顧客一要十串鴨肉" type:orderTypeDuck];
[waiter addOrder:customerOrder1];
[waiter addOrder:customerOrder2];
//顧客二
HCDCustomr *customer1 = [[HCDCustomr alloc]init];
HCDOrder *customer1Order1 = [customer1 pushOrderWithString:@"顧客二要二十串雞肉" type:orderTypeChicken];
HCDOrder *customer1Order2 = [customer1 pushOrderWithString:@"顧客二要二十串鴨肉" type:orderTypeDuck];
[waiter addOrder:customer1Order1];
[waiter addOrder:customer1Order2];
[waiter deleteOrder:customer1Order2];
//waiter發(fā)送order,背后有一個(gè)HCDWorker這個(gè)單列作為行為實(shí)現(xiàn)者來(lái)處理具體的order伍纫。命令接收完畢宗雇,開(kāi)始發(fā)送命令。
[waiter notifyOrder];
//HCDCustomr.m
@implementation HCDCustomr
-(HCDOrder *)pushOrderWithString:(NSString *)string type:(orderType)type{
HCDOrder *order = nil;
switch (type) {
case orderTypeMutton:
order = [[HCDMuttonOrder alloc]initWithOrderString:string];
break;
case orderTypeChicken:
order = [[HCDChickenOrder alloc]initWithOrderString:string];
break;
case orderTypeDuck:
order = [[HCDDuckOrder alloc]initWithOrderString:string];
break;
}
return order;
}
@end
//HCDWaiter.m
@implementation HCDWaiter
-(instancetype)init{
self = [super init];
if (self) {
_orderList = [NSMutableArray array];
}
return self;
}
-(void)addOrder:(HCDOrder *)order{
NSLog(@"添加Order");
[self.orderList addObject:order];
}
-(void)deleteOrder:(HCDOrder *)order{
NSLog(@"取消Order");
[self.orderList removeObject:order];
}
/*
命令接收完畢莹规,開(kāi)始執(zhí)行命令
*/
-(void)notifyOrder{
NSLog(@"====開(kāi)始執(zhí)行Order===");
for (HCDOrder *order in self.orderList) {
[order executeOrder];
}
}
@end
//HCDOrder.h
@interface HCDOrder : NSObject
@property(nonatomic,copy)NSString *orderString;
-(instancetype)initWithOrderString:(NSString *)orderString;
//執(zhí)行命令
-(void)executeOrder;
@end
//HCDMuttonOrder.m
@implementation HCDMuttonOrder
-(void)executeOrder{
NSLog(@"烤羊");
[[HCDWorker sharedWorker] doMuttonWork:self.orderString];
}
@end
//HCDChickenOrder.m
@implementation HCDChickenOrder
-(void)executeOrder{
NSLog(@"烤雞");
[[HCDWorker sharedWorker] doChickenWork:self.orderString];
}
@end
//HCDDuckOrder.m
@implementation HCDDuckOrder
-(void)executeOrder{
NSLog(@"烤鴨");
[[HCDWorker sharedWorker] doChickenWork:self.orderString];
}
@end
//HCDWorker.h
@interface HCDWorker : NSObject
+(instancetype)sharedWorker;
-(void)doMuttonWork:(NSString *)work;
-(void)doChickenWork:(NSString *)work;
-(void)doDuckWork:(NSString *)work;
@end
中介者模式
模式動(dòng)機(jī)
- 在用戶與用戶直接聊天的設(shè)計(jì)方案中赔蒲,用戶對(duì)象之間存在很強(qiáng)的關(guān)聯(lián)性,將導(dǎo)致系統(tǒng)出現(xiàn)如下問(wèn)題:
- 系統(tǒng)結(jié)構(gòu)復(fù)雜:對(duì)象之間存在大量的相互關(guān)聯(lián)和調(diào)用良漱,若有一個(gè)對(duì)象發(fā)生變化舞虱,則需要跟蹤和該對(duì)象關(guān)聯(lián)的其他所有對(duì)象,并進(jìn)行適當(dāng)處理母市。
- 對(duì)象可重用性差:由于一個(gè)對(duì)象和其他對(duì)象具有很強(qiáng)的關(guān)聯(lián)矾兜,若沒(méi)有其他對(duì)象的支持,一個(gè)對(duì)象很難被另一個(gè)系統(tǒng)或模塊重用患久,這些對(duì)象表現(xiàn)出來(lái)更像一個(gè)不可分割的整體椅寺,職責(zé)較為混亂浑槽。
- 系統(tǒng)擴(kuò)展性低:增加一個(gè)新的對(duì)象需要在原有相關(guān)對(duì)象上增加引用,增加新的引用關(guān)系也需要調(diào)整原有對(duì)象配并,系統(tǒng)耦合度很高括荡,對(duì)象操作很不靈活,擴(kuò)展性差溉旋。
- 在面向?qū)ο蟮能浖O(shè)計(jì)與開(kāi)發(fā)過(guò)程中畸冲,根據(jù)“單一職責(zé)原則”,我們應(yīng)該盡量將對(duì)象細(xì)化观腊,使其只負(fù)責(zé)或呈現(xiàn)單一的職責(zé)邑闲。
- 對(duì)于一個(gè)模塊,可能由很多對(duì)象構(gòu)成梧油,而且這些對(duì)象之間可能存在相互的引用苫耸,為了減少對(duì)象兩兩之間復(fù)雜的引用關(guān)系,使之成為一個(gè)松耦合的系統(tǒng)儡陨,我們需要使用中介者模式褪子,這就是中介者模式的模式動(dòng)機(jī)。
模式定義
中介者模式(Mediator Pattern)定義:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互骗村,中介者使各對(duì)象不需要顯式地相互引用嫌褪,從而使其耦合松散,而且可以獨(dú)立地改變它們之間的交互胚股。它是一種對(duì)象行為型模式笼痛。
模式結(jié)構(gòu)
中介者模式包含如下角色:
- Mediator: 抽象中介者
- ConcreteMediator: 具體中介者
- Colleague: 抽象同事類
-
ConcreteColleague: 具體同事類
中介者模式類圖
時(shí)序圖
源碼
//使用示例
ConcreteMediator *mediator = [[ConcreteMediator alloc] init];
//初始化并且讓兩個(gè)同事有相同的中介者對(duì)象
ConcreteColleague1 *c1 = [[ConcreteColleague1 alloc] initWithMediator:mediator];
ConcreteColleague2 *c2 = [[ConcreteColleague2 alloc] initWithMediator:mediator];
//給中介者對(duì)象綁定兩個(gè)要交互的同事對(duì)象
mediator.colleague1 = c1;
mediator.colleague2 = c2;
[c1 send:@"吃過(guò)飯了嗎?"];
[c2 send:@"沒(méi)有呢琅拌,你打算請(qǐng)客缨伊?"];
//Mediator.h
@class Colleague;
@interface Mediator : NSObject
@property (nonatomic, strong) Colleague *colleague1;
@property (nonatomic, strong) Colleague *colleague2;
-(void)send:(NSString *)message colleague:(Colleague *)colleague;
@end
//ConcreteMediator.m
@implementation ConcreteMediator
-(void)send:(NSString *)message colleague:(Colleague *)colleague{
if (colleague == self.colleague1) {
[self.colleague2 notify:message];
}else{
[self.colleague1 notify:message];
}
}
@end
//Colleague.h
@class Mediator;
@interface Colleague : NSObject
@property(nonatomic, strong) Mediator *mediator;
-(instancetype)initWithMediator:(Mediator *)mediator;
-(void)notify:(NSString *)message;
-(void)send:(NSString *)message;
@end
//ConcreteColleague1.m
@implementation ConcreteColleague1
-(instancetype)initWithMediator:(Mediator *)mediator{
self = [super init];
if (self) {
self.mediator = mediator;
}
return self;
}
-(void)send:(NSString *)message{
NSLog(@"同事1發(fā)送了信息");
[self.mediator send:message colleague:self];
}
-(void)notify:(NSString *)message{
NSLog(@"%@%@",@"同事1得到消息:", message);
}
@end
//ConcreteColleague2.m
@implementation ConcreteColleague2
-(instancetype)initWithMediator:(Mediator *)mediator{
self = [super init];
if (self) {
self.mediator = mediator;
}
return self;
}
-(void)send:(NSString *)message{
NSLog(@"同事2發(fā)送了信息");
[self.mediator send:message colleague:self];
}
-(void)notify:(NSString *)message{
NSLog(@"%@%@",@"同事2得到消息", message);
}
@end
觀察者模式
模式動(dòng)機(jī)
建立一種對(duì)象與對(duì)象之間的依賴關(guān)系,一個(gè)對(duì)象發(fā)生改變時(shí)將自動(dòng)通知其他對(duì)象进宝,其他對(duì)象將相應(yīng)做出反應(yīng)刻坊。在此,發(fā)生改變的對(duì)象稱為觀察目標(biāo)即彪,而被通知的對(duì)象稱為觀察者紧唱,一個(gè)觀察目標(biāo)可以對(duì)應(yīng)多個(gè)觀察者,而且這些觀察者之間沒(méi)有相互聯(lián)系隶校,可以根據(jù)需要增加和刪除觀察者漏益,使得系統(tǒng)更易于擴(kuò)展,這就是觀察者模式的模式動(dòng)機(jī)深胳。
模式定義
觀察者模式(Observer Pattern):定義對(duì)象間的一種一對(duì)多依賴關(guān)系绰疤,使得每當(dāng)一個(gè)對(duì)象狀態(tài)發(fā)生改變時(shí),其相關(guān)依賴對(duì)象皆得到通知并被自動(dòng)更新舞终。觀察者模式是一種對(duì)象行為型模式轻庆。
模式結(jié)構(gòu)
觀察者模式包含如下角色:
- Subject: 目標(biāo)
- ConcreteSubject: 具體目標(biāo)
- Observer: 觀察者
-
ConcreteObserver: 具體觀察者
觀察者模式類圖
時(shí)序圖
源碼
//使用示例
- (void)viewDidLoad {
[super viewDidLoad];
HCDServiceCenter *serviceCenter = [[HCDServiceCenter alloc] init];
[serviceCenter addDelegate:self.nbaobserver];
[serviceCenter addDelegate:self.stockobserver];
[serviceCenter addDelegate:self.gameObserver];
NSLog(@"秘書(shū)通知:老板回來(lái)了癣猾,大家趕緊撤");
[serviceCenter notifyServiceDelegate:@selector(update)
perform:^(id responder) {
[responder update];
}];
}
#pragma mark - getter & setter
-(HCDNBAObserver *)nbaobserver {
if (!_nbaobserver) {
_nbaobserver = [[HCDNBAObserver alloc] init];
}
return _nbaobserver;
}
-(HCDStockObserver *)stockobserver {
if (!_stockobserver) {
_stockobserver = [[HCDStockObserver alloc] init];
}
return _stockobserver;
}
-(HCDGameObserver *)gameObserver {
if (!_gameObserver) {
_gameObserver = [[HCDGameObserver alloc] init];
}
return _gameObserver;
}
//HCDServiceCenter.h
@interface HCDServiceCenter : NSObject
@property(nonatomic, strong, readonly) NSHashTable *responders;
- (instancetype)initWithNotifyQueue:(dispatch_queue_t)notifyQueue;
- (void)addDelegate:(id)delegate;
- (void)removeDelegate:(id)delegate;
- (void)notifyServiceDelegate:(SEL)aSelector
perform:(void (^)(id responder))perform;
@end
//HCDServiceCenter.m
#define LOCK(...) dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); \
__VA_ARGS__; \
dispatch_semaphore_signal(_lock);
@interface HCDServiceCenter()
@property(nonatomic, strong) dispatch_queue_t notifyQueue;
@property(nonatomic, strong) NSHashTable *responders;
@end
@implementation HCDServiceCenter {
dispatch_semaphore_t _lock;
}
- (instancetype)init {
self = [super init];
if (self) {
self.responders = [NSHashTable weakObjectsHashTable];
self.notifyQueue = dispatch_get_main_queue();
_lock = dispatch_semaphore_create(1);
}
return self;
}
- (instancetype)initWithNotifyQueue:(dispatch_queue_t)notifyQueue {
self = [super init];
if (self) {
self.responders = [NSHashTable weakObjectsHashTable];
self.notifyQueue = notifyQueue;
}
return self;
}
- (void)addDelegate:(id)delegate {
LOCK([self.responders addObject:delegate]);
}
- (void)removeDelegate:(id)delegate {
LOCK([self.responders removeObject:delegate]);
}
- (void)notifyServiceDelegate:(SEL)aSelector
perform:(void (^)(id responder))perform {
dispatch_async(self.notifyQueue, ^{
NSArray *responders = self.responders.allObjects;
for (id responder in responders) {
if ([responder respondsToSelector:aSelector]) {
@try {
perform(responder);
}
@catch (NSException *exception) {
NSLog(@"catch notifyServiceDelegate exception: %@", exception);
}
}
}
});
}
@end
//HCDObserver.h
@protocol HCDObserver <NSObject>
@optional
- (void)update;
@end
//HCDStockObserver.h
@interface HCDStockObserver : NSObject<HCDObserver>
@end
//HCDNBAObserver.h
@interface HCDNBAObserver : NSObject<HCDObserver>
@end
//HCDGameObserver.h
@interface HCDGameObserver : NSObject<HCDObserver>
@end
狀態(tài)模式
模式動(dòng)機(jī)
在很多情況下,一個(gè)對(duì)象的行為取決于一個(gè)或多個(gè)動(dòng)態(tài)變化的屬性余爆,這樣的屬性叫做狀態(tài)纷宇,這樣的對(duì)象叫做有狀態(tài)的(stateful)對(duì)象,這樣的對(duì)象狀態(tài)是從事先定義好的一系列值中取出的蛾方。當(dāng)一個(gè)這樣的對(duì)象與外部事件產(chǎn)生互動(dòng)時(shí)像捶,其內(nèi)部狀態(tài)就會(huì)改變,從而使得系統(tǒng)的行為也隨之發(fā)生變化桩砰。
狀態(tài)模式主要解決的是當(dāng)控制一個(gè)對(duì)象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過(guò)于負(fù)責(zé)時(shí)的情況拓春。把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類當(dāng)中,可以把復(fù)雜的判斷邏輯簡(jiǎn)化亚隅。
模式定義
允許一個(gè)對(duì)象在其內(nèi)部狀態(tài)改變時(shí)改變它的行為硼莽,對(duì)象看起來(lái)似乎修改了它的類。狀態(tài)模式是一種對(duì)象行為型模式煮纵。
模式結(jié)構(gòu)
狀態(tài)模式包含如下角色:
- Context: 環(huán)境類
- State: 抽象狀態(tài)類
-
ConcreteState: 具體狀態(tài)類
狀態(tài)模式類圖
時(shí)序圖
源碼
//使用示例
HCDWork *work = [[HCDWork alloc]init];
work.hour = 9;
[work writeProgram];
work.hour = 10;
[work writeProgram];
work.hour = 12;
[work writeProgram];
work.hour = 13;
[work writeProgram];
work.hour = 14;
[work writeProgram];
work.hour = 17;
[work writeProgram];
work.finished = NO;
[work writeProgram];
work.hour = 19;
[work writeProgram];
work.hour = 22;
[work writeProgram];
//HCDWork.h
@interface HCDWork : NSObject
@property(nonatomic, assign) CGFloat hour;
@property(nonatomic, assign) BOOL finished;
- (void)writeProgram;
- (void)changeState:(HCDState *)state;
@end
//HCDWork.m
@interface HCDWork()
@property (nonatomic, strong) HCDState *state;
@end
@implementation HCDWork
- (instancetype)init{
self = [super init];
if (self) {
self.state = [[HCDForenoonState alloc]init];
}
return self;
}
- (void)writeProgram {
[self.state writeProgram:self];
}
- (void)changeState:(HCDState *)state {
self.state = state;
}
@end
//HCDProtocol.h
@class HCDWork;
@protocol HCDProtocol <NSObject>
@optional
- (void)writeProgram:(HCDWork *)work;
@end
//HCDState.h
@interface HCDState : NSObject<HCDProtocol>
@end
//HCDForenoonState.m
@implementation HCDForenoonState
-(void)writeProgram:(HCDWork *)work{
if (work.hour < 12) {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)懂鸵,上午工作,精神百倍", work.hour);
}else{
HCDNoonState *noonState = [[HCDNoonState alloc] init];
[work changeState:noonState];
[work writeProgram];
}
}
@end
//HCDNoonState.m
@implementation HCDNoonState
-(void)writeProgram:(HCDWork *)work{
if (work.hour < 13) {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)行疏,餓了矾瑰,午飯;犯困隘擎,午休", work.hour);
} else {
HCDAfternoonState *afternoonState = [[HCDAfternoonState alloc] init];
[work changeState:afternoonState];
[work writeProgram];
}
}
@end
//HCDAfternoonState.m
@implementation HCDAfternoonState
-(void)writeProgram:(HCDWork *)work{
if (work.hour < 17) {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn),下午狀態(tài)還不錯(cuò)凉夯,繼續(xù)努力", work.hour);
} else {
HCDEventState *eventState = [[HCDEventState alloc] init];
[work changeState:eventState];
[work writeProgram];
}
}
@end
//HCDEventState.m
@implementation HCDEventState
-(void)writeProgram:(HCDWork *)work{
if (work.finished) {
HCDRestState *restState = [[HCDRestState alloc] init];
[work changeState:restState];
[work writeProgram];
} else {
if (work.hour < 21) {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)货葬,加班哦,疲累之極", work.hour);
} else {
HCDSleepState *sleepState = [[HCDSleepState alloc] init];
[work changeState:sleepState];
[work writeProgram];
}
}
}
@end
//HCDSleepState.m
@implementation HCDSleepState
- (void)writeProgram:(HCDWork *)work {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn)劲够,不行了震桶,睡著了", work.hour);
}
@end
//HCDRestState.m
@implementation HCDRestState
- (void)writeProgram:(HCDWork *)work {
NSLog(@"當(dāng)前時(shí)間:{%.f}點(diǎn),下班回家了", work.hour);
}
@end
策略模式
模式動(dòng)機(jī)
- 完成一項(xiàng)任務(wù)征绎,往往可以有多種不同的方式蹲姐,每一種方式稱為一個(gè)策略,我們可以根據(jù)環(huán)境或者條件的不同選擇不同的策略來(lái)完成該項(xiàng)任務(wù)人柿。
- 在軟件開(kāi)發(fā)中也常常遇到類似的情況柴墩,實(shí)現(xiàn)某一個(gè)功能有多個(gè)途徑,此時(shí)可以使用一種設(shè)計(jì)模式來(lái)使得系統(tǒng)可以靈活地選擇解決途徑凫岖,也能夠方便地增加新的解決途徑江咳。
- 為了解決這些問(wèn)題,可以定義一些獨(dú)立的類來(lái)封裝不同的算法哥放,每一個(gè)類封裝一個(gè)具體的算法歼指,在這里爹土,每一個(gè)封裝算法的類我們都可以稱之為策略(Strategy),為了保證這些策略的一致性踩身,一般會(huì)用一個(gè)抽象的策略類來(lái)做算法的定義胀茵,而具體每種算法則對(duì)應(yīng)于一個(gè)具體策略類。
模式定義
定義了算法家族挟阻,分別封裝起來(lái)琼娘,讓它們之間可以互相替換,此模式讓算法的變化赁濒,不會(huì)影響到使用算法的客戶轨奄。
模式結(jié)構(gòu)
策略模式包含如下角色:
- Context: 環(huán)境類
- Strategy: 抽象策略類
- ConcreteStrategy: 具體策略類
時(shí)序圖
源碼
//使用示例
HCDCashContext *context = [[HCDCashContext alloc] initWithCashType:HCDCashTypeNormal];
NSLog(@"結(jié)果是%f",[context getResult:100]);
HCDCashContext *contextReturn = [[HCDCashContext alloc] initWithCashType:HCDCashTypeReturn];
NSLog(@"結(jié)果是%f",[contextReturn getResult:100]);
HCDCashContext *contextRobate = [[HCDCashContext alloc] initWithCashType:HCDCashTypeRobate];
NSLog(@"結(jié)果是%f",[contextRobate getResult:100]);
//HCDCashContext.h
typedef NS_ENUM(NSInteger, HCDCashType){
HCDCashTypeNormal = 0,
HCDCashTypeRobate,
HCDCashTypeReturn
};
@interface HCDCashContext : NSObject
-(instancetype)initWithCashType:(HCDCashType)type;
-(CGFloat)getResult:(CGFloat)money;
@end
//HCDCashContext.m
@interface HCDCashContext()
@property (nonatomic, strong) id<HCDCashProtocol> cash;
@end
@implementation HCDCashContext
-(instancetype)initWithCashType:(HCDCashType)type{
self = [super init];
if (self) {
[self cofigureWithCashType:type];
}
return self;
}
- (void)cofigureWithCashType:(HCDCashType)type {
switch (type) {
case HCDCashTypeNormal: {
self.cash = [[HCDCashNormal alloc] init];
}
break;
case HCDCashTypeRobate: {
self.cash = [[HCDCashRobate alloc] initWithMoneyRebate:0.8];
}
break;
case HCDCashTypeReturn: {
self.cash = [[HCDCaseReturn alloc] initWithMoneyReturn:5];
}
break;
}
}
- (CGFloat)getResult:(CGFloat)money {
return [self.cash acceptCash:money];
}
@end
//HCDCashProtocol.h
@protocol HCDCashProtocol <NSObject>
- (CGFloat)acceptCash:(CGFloat)cash;
@end
//HCDCaseReturn.h
@interface HCDCaseReturn : NSObject<HCDCashProtocol>
-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn;
@end
//HCDCaseReturn.m
@interface HCDCaseReturn ()
@property (nonatomic, assign)CGFloat moneyReturn;
@end
@implementation HCDCaseReturn
#pragma mark - life cycle
-(instancetype)initWithMoneyReturn:(CGFloat)moneyReturn{
self = [super init];
if (self) {
_moneyReturn = moneyReturn;
}
return self;
}
#pragma mark - HCDCashProtocol
-(CGFloat)acceptCash:(CGFloat)cash{
return cash - self.moneyReturn;
}
@end
//HCDCashNormal.m
@implementation HCDCashNormal
-(CGFloat)acceptCash:(CGFloat)cash{
return cash;
}
@end
//HCDCashRobate.h
@interface HCDCashRobate : NSObject<HCDCashProtocol>
-(instancetype)initWithMoneyRebate:(CGFloat)moneyRebate;
@end
//HCDCashRobate.m
@interface HCDCashRobate ()
@property (nonatomic, assign) CGFloat moneyRebate;
@end
@implementation HCDCashRobate
-(instancetype)initWithMoneyRebate:(CGFloat)moneyRebate{
self = [super init];
if (self) {
_moneyRebate = moneyRebate;
}
return self;
}
-(CGFloat)acceptCash:(CGFloat)cash{
return self.moneyRebate * cash;
}
@end
模板方法模式
模式動(dòng)機(jī)
模板方法模式是基于繼承的代碼復(fù)用基本技術(shù),模板方法模式的結(jié)構(gòu)和用法也是面向?qū)ο笤O(shè)計(jì)的核心之一拒炎。
在模板方法模式中挪拟,可以將相同的代碼放在父類中,而將不同的方法實(shí)現(xiàn)放在不同的子類中。
模式定義
定義一個(gè)操作中的算法的骨架,而將一些步驟延遲到子類中锈玉。模板方法使得子類可以不改變一個(gè)算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟惹苗。
模式結(jié)構(gòu)
模板方法模式包含如下角色:
- AbstractClass: 抽象類
-
ConcreteClass: 具體子類
模板方法模式類圖
時(shí)序圖
略
源碼
//使用示例
HCDtextPaper *paperA = [[HCDtextPaperA alloc]init];
[paperA testQuestion1];
[paperA testQuestion2];
HCDtextPaper *paperB = [[HCDtextPaperB alloc]init];
[paperB testQuestion1];
[paperB testQuestion2];
//HCDtextPaper.h
@interface HCDtextPaper : NSObject
- (void)testQuestion1;
- (void)testQuestion2;
/**
子類需要重寫(xiě)這個(gè)方法
@return 結(jié)果
*/
- (NSString *)answer1;
/**
子類需要重寫(xiě)這個(gè)方法
@return 結(jié)果
*/
- (NSString *)answer2;
@end
//HCDtextPaper.m
@implementation HCDtextPaper
-(void)testQuestion1 {
NSLog(@"問(wèn)題:楊過(guò)得到,后來(lái)給了郭靖邪驮,煉成倚天劍、屠龍刀的玄鐵可能是[ ]:a.球磨鑄鐵 b.馬口鐵 c.高速合金鋼 d.碳素纖維");
NSLog(@"答案:%@", [self answer1]);
}
-(NSString *)answer1 {
return @"";
}
-(void)testQuestion2 {
NSLog(@"問(wèn)題:楊過(guò)、程英石景、陸無(wú)雙鏟除了情花,造成[ ]:a.使這種植物不再害人 b.使一種珍稀物種滅絕 c.破壞了那個(gè)生物圈的生態(tài)平衡 d.造成該地區(qū)沙漠化");
NSLog(@"答案:%@", [self answer2]);
}
-(NSString *)answer2{
return @"";
}
@end
//HCDtextPaperA.m
@implementation HCDtextPaperA
-(NSString *)answer1{
return @"b";
}
-(NSString *)answer2{
return @"c";
}
@end
//HCDtextPaperB.m
@implementation HCDtextPaperB
-(NSString *)answer1{
return @"a";
}
-(NSString *)answer2{
return @"d";
}
@end
職責(zé)鏈模式
模式動(dòng)機(jī)
很多情況下拙吉,在一個(gè)軟件系統(tǒng)中可以處理某個(gè)請(qǐng)求的對(duì)象不止一個(gè)潮孽。例如采購(gòu)審批子系統(tǒng),主任筷黔、副董事長(zhǎng)往史、董事長(zhǎng)和董事會(huì)都可以處理采購(gòu)單,他們可以構(gòu)成一條處理采購(gòu)單的鏈?zhǔn)浇Y(jié)構(gòu)佛舱,采購(gòu)單(可以看作是要處理的信息)沿著這條鏈進(jìn)行傳遞椎例,這條鏈就稱為責(zé)任鏈。責(zé)任鏈可以是一條直線请祖、一個(gè)環(huán)或者一個(gè)樹(shù)形結(jié)構(gòu)订歪,最常見(jiàn)的職責(zé)鏈?zhǔn)侵本€型,即沿著一條單向的鏈來(lái)傳遞請(qǐng)求损拢,如下圖所示陌粹。鏈上的每一個(gè)對(duì)象都是請(qǐng)求處理者,責(zé)任鏈模式可以將請(qǐng)求的處理者組織成一條鏈,并讓請(qǐng)求沿著鏈傳遞掏秩,由鏈上的處理者對(duì)請(qǐng)求進(jìn)行相應(yīng)的處理或舞。在此過(guò)程中,客戶端實(shí)際上無(wú)須關(guān)心請(qǐng)求的處理細(xì)節(jié)以及請(qǐng)求的傳遞蒙幻,只需將請(qǐng)求發(fā)送到鏈上即可映凳,從而實(shí)現(xiàn)請(qǐng)求發(fā)送者和請(qǐng)求處理者解耦。
模式定義
使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求邮破,從而避免請(qǐng)求的發(fā)送者和接受者之間的耦合關(guān)系诈豌。將這個(gè)對(duì)象連成一條鏈,并沿著這條鏈傳遞該請(qǐng)求抒和,直到有一個(gè)對(duì)象處理它為止矫渔。
模式結(jié)構(gòu)
職責(zé)鏈模式包含如下角色:
- Handler: 處理者抽象類
- ConcreteAggregate: 具體處理者類
時(shí)序圖
略
源碼
//使用示例
HCDCommonManager *jinli = [[HCDCommonManager alloc]initWithName:@"經(jīng)理"];
HCDMajorManager *zongjian = [[HCDMajorManager alloc]initWithName:@"總監(jiān)"];
HCDGenaralManager *zongjinli = [[HCDGenaralManager alloc]initWithName:@"總經(jīng)理"];
jinli.superior = zongjian;
zongjian.superior = zongjinli;
HCDReuquest *request = [[HCDReuquest alloc] init];
request.requestType = @"請(qǐng)假";
request.requestContent = @"小菜請(qǐng)假";
request.number = 1;
[jinli dealRequest:request];
HCDReuquest *request1 = [[HCDReuquest alloc] init];
request1.requestType = @"請(qǐng)假";
request1.requestContent = @"小菜請(qǐng)假";
request1.number = 4;
[jinli dealRequest:request1];
HCDReuquest *request2 = [[HCDReuquest alloc] init];
request2.requestType = @"加薪";
request2.requestContent = @"小菜請(qǐng)求加薪";
request2.number = 500;
[jinli dealRequest:request2];
HCDReuquest *request4 = [[HCDReuquest alloc] init];
request4.requestType = @"加薪";
request4.requestContent = @"小菜請(qǐng)求加薪";
request4.number = 1000;
[jinli dealRequest:request4];
//HCDMnager.h
@class HCDReuquest;
@interface HCDMnager : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) HCDMnager *superior;
- (instancetype)initWithName:(NSString *)name;
- (void)dealRequest:(HCDReuquest *)request;
@end
//HCDCommonManager.h
@interface HCDCommonManager : HCDMnager
@end
//HCDCommonManager.m
@implementation HCDCommonManager
- (void)dealRequest:(HCDReuquest *)request{
if ([request.requestType isEqualToString:@"請(qǐng)假"] && request.number <= 2) {
NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
}else{
if (self.superior) {
[self.superior dealRequest:request];
}
}
}
@end
//HCDMajorManager.h
@interface HCDMajorManager : HCDMnager
@end
//HCDMajorManager.m
@implementation HCDMajorManager
-(void)dealRequest:(HCDReuquest *)request{
if ([request.requestType isEqualToString:@"請(qǐng)假"] && request.number <= 5) {
NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
}else{
if (self.superior) {
[self.superior dealRequest:request];
}
}
}
@end
//HCDGenaralManager.h
@interface HCDGenaralManager : HCDMnager
@end
//HCDGenaralManager.m
@implementation HCDGenaralManager
-(void)dealRequest:(HCDReuquest *)request{
if ([request.requestType isEqualToString:@"請(qǐng)假"]) {
NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
} else if ([request.requestType isEqualToString:@"加薪"]){
if (request.number <= 500) {
NSLog(@"%@:%@ 數(shù)量%ld 被批準(zhǔn)",self.name,request.requestType,request.number);
} else {
NSLog(@"%@:%@ 數(shù)量%ld 再說(shuō)吧",self.name,request.requestType,request.number);
}
} else {
}
}
@end
//HCDReuquest.h
@interface HCDReuquest : NSObject
/**
請(qǐng)求類型
*/
@property (nonatomic, copy) NSString *requestType;
/**
請(qǐng)求內(nèi)容
*/
@property (nonatomic, copy) NSString *requestContent;
/**
請(qǐng)求的數(shù)量
*/
@property(nonatomic, assign) NSInteger number;
@end
解釋器模式
模式動(dòng)機(jī)
如果在系統(tǒng)中某一特定類型的問(wèn)題發(fā)生的頻率很高,此時(shí)可以考慮將這些問(wèn)題的實(shí)例表述為一個(gè)語(yǔ)言中的句子摧莽,因此可以構(gòu)建一個(gè)解釋器庙洼,該解釋器通過(guò)解釋這些句子來(lái)解決這些問(wèn)題。
解釋器模式描述了如何構(gòu)成一個(gè)簡(jiǎn)單的語(yǔ)言解釋器镊辕,主要應(yīng)用在使用面向?qū)ο笳Z(yǔ)言開(kāi)發(fā)的編譯器中油够。
模式定義
給定一種語(yǔ)言,定義它的文法的一種表示征懈,并定義一個(gè)解釋器石咬,這個(gè)解釋器使用該表示來(lái)解釋語(yǔ)言中的句子。
模式結(jié)構(gòu)
解釋器模式模式包含如下角色:
- AbstractExpression: 抽象表達(dá)式
- TerminalExpression: 終結(jié)符表達(dá)式
- NonterminalExpression: 非終結(jié)符表達(dá)式
- Context: 環(huán)境類
-
Client: 客戶類
解釋器模式類圖
時(shí)序圖
略
源碼
略
訪問(wèn)者模式
模式動(dòng)機(jī)
訪問(wèn)者模式的目的是封裝一些施加于某種數(shù)據(jù)結(jié)構(gòu)元素之上的操作卖哎,一旦這些操作需要修改的話鬼悠,接受這個(gè)操作的數(shù)據(jù)結(jié)構(gòu)可以保持不變。為不同類型的元素提供多種訪問(wèn)操作方式亏娜,且可以在不修改原有系統(tǒng)的情況下增加新的操作方式厦章,這就是訪問(wèn)者模式的模式動(dòng)機(jī)。
模式定義
表示一個(gè)作用于某對(duì)象結(jié)構(gòu)中的各元素的操作照藻。它使你可以在不改變各元素的類的前提下定義作用于這些元素的新操作。
模式結(jié)構(gòu)
訪問(wèn)者模式包含如下角色:
- Vistor: 抽象訪問(wèn)者汗侵。為該對(duì)象結(jié)構(gòu)中的ConcreteElement的每一個(gè)類聲明的一個(gè)操作幸缕。
- ConcreteVisitor: 具體訪問(wèn)者。實(shí)現(xiàn)Visitor申明的每一個(gè)操作晰韵,每一個(gè)操作實(shí)現(xiàn)算法的一部分发乔。
- Element: 抽象元素。定義一個(gè)Accept操作雪猪,它以一個(gè)訪問(wèn)者為參數(shù)栏尚。
- ConcreteElement: 具體元素 。實(shí)現(xiàn)Accept操作只恨。
-
ObjectStructure: 對(duì)象結(jié)構(gòu)译仗。能夠枚舉它的元素抬虽,可以提供一個(gè)高層的接口來(lái)允許訪問(wèn)者訪問(wèn)它的元素。
訪問(wèn)者模式類圖
時(shí)序圖
略
源碼
//使用示例
HCDObjectStructure *o = [[HCDObjectStructure alloc]init];
//初始化不同的element對(duì)象
HCDConcreteElementA *eA = [HCDConcreteElementA new];
HCDConcreteElementB *eB = [HCDConcreteElementB new];
//加入o對(duì)象里面纵菌,存在一個(gè)數(shù)據(jù)結(jié)構(gòu)o中阐污。
[o attach:eA];
[o attach:eB];
//初始化不同的visitor對(duì)象。
HCDConcreteVisitor1 *v1 = [HCDConcreteVisitor1 new];
HCDConcreteVisitor2 *v2 = [HCDConcreteVisitor2 new];
//eA,eB(男人女人)接收到訪問(wèn)者v1(喜)的不同反應(yīng)咱圆。
[o accept:v1];
NSLog(@"================================");
//eA,eB(男人女人)接收到訪問(wèn)者v2(怒)的不同反應(yīng)笛辟。
[o accept:v2];
//HCDObjectStructure.h
@class HCDElements;
@class HCDVisitors;
@interface HCDObjectStructure : NSObject
-(void)attach:(HCDElements *)element;
-(void)detach:(HCDElements *)element;
-(void)accept:(HCDVisitors *)visitor;
@end
//HCDObjectStructure.m
@interface HCDObjectStructure ()
@property (nonatomic, strong) NSMutableArray *elements;
@end
@implementation HCDObjectStructure
-(instancetype)init{
self = [super init];
if (self) {
_elements = [[NSMutableArray alloc]init];
}
return self;
}
-(void)attach:(HCDElements *)element{
[self.elements addObject:element];
}
-(void)detach:(HCDElements *)element{
[self.elements removeObject:element];
}
-(void)accept:(HCDVisitors *)visitor{
for (HCDElements *e in self.elements) {
[e accept:visitor];
}
}
@end
//HCDVisitors.h
@interface HCDVisitors : NSObject
-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA;
-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB;
@end
//HCDConcreteVisitor1.h
@interface HCDConcreteVisitor1 : HCDVisitors
@end
//HCDConcreteVisitor1.m
@implementation HCDConcreteVisitor1
-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA{
NSLog(@"男人接收到喜這個(gè)visitor============我要飛");
}
-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB{
NSLog(@"女人接收到喜這個(gè)visitor============我要跳");
}
@end
//HCDConcreteVisitor2.h
@interface HCDConcreteVisitor2 : HCDVisitors
@end
//HCDConcreteVisitor2.m
@implementation HCDConcreteVisitor2
-(void)visitConcreteElementA:(HCDConcreteElementA *)concreteElementA{
NSLog(@"男人接收到怒這個(gè)visitor============我要叫");
}
-(void)visitConcreteElementB:(HCDConcreteElementB *)concreteElementB{
NSLog(@"女人接收到怒這個(gè)visitor============我要苦");
}
@end
//HCDElements.h
@class HCDVisitors;
@interface HCDElements : NSObject
-(void)accept:(HCDVisitors *)visitor;
@end
//HCDConcreteElementA.m
@implementation HCDConcreteElementA
-(void)operationA{
return;
}
-(void)accept:(HCDVisitors *)visitor{
[visitor visitConcreteElementA:self];
}
@end
//HCDConcreteElementB.m
@implementation HCDConcreteElementB
-(void)operationB{
return;
}
-(void)accept:(HCDVisitors *)visitor{
[visitor visitConcreteElementB:self];
}
@end
小結(jié)
在實(shí)際的項(xiàng)目開(kāi)發(fā)過(guò)程中,使用某些特定的設(shè)計(jì)模式能夠很好的解決問(wèn)題序苏。同時(shí)手幢,在維護(hù)他人編寫(xiě)的代碼時(shí),如果對(duì)設(shè)計(jì)模式特別熟悉忱详,遇到時(shí)也比較容易定位問(wèn)題围来。
源碼和demo請(qǐng)點(diǎn)這里
參考的文章鏈接如下
Graphic Design Patterns