模板方法模式的核心思想就是通過把不變的行為搬移到超類,去除子類中的重複代碼來體現它的優勢。其實,模板方法模式就是提供了一個很好的代碼複用平台。
首先,還是先簡單看一下定義:
模板方法模式,定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。模板方法使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
下面和給大家展示一下類的結構圖:
其實,結構很簡單,只有兩層關係,核心思想就是把公用方法向上提到父類中。代碼實現起來也不複雜。下面還是老樣子,向大家簡單展示一下代碼如何?。
首先是一個protocol,相當於java裡的interface:
複製代碼 代碼如下:
// 初始化指令碼協議
@protocol YLSInitialScript <NSObject>
- (void) doInit:(YLSClientInfo*) clientInfo;
@end
然後定義一個抽象類別,實現這個介面的總體架構性演算法,但是具體的實現聲明為抽象方法:
複製代碼 代碼如下:
@interface YLSInitialScriptTemplate : NSObject<YLSInitialScript>
-(id) initOrigin:(YLSInitialOperator *)operator;
// 抽象方法,由子類實現
- (void) createEverythingForFirstTime;
- (void) update;
- (NSString*) stepMsg;
@end
複製代碼 代碼如下:
@implementation YLSInitialScriptTemplate
YLSInitialOperator *origin;
-(id) initOrigin:(YLSInitialOperator *)operator
{
origin = operator;
return self;
}
- (void) doInit:(YLSClientInfo*) clientInfo
{
if ([clientInfo shouldInit]) {
[self createEverythingForFirstTime];// 無表,初始化
} else if ([clientInfo shouldUpdate]) {
[self update];// 升級
}
[origin notifyStepDone:[self stepMsg]];// 通知Bootstrap View Controller重新整理進度條
}
// 以下3個是抽象方法,延遲到子類實現
- (void) createEverythingForFirstTime
{
[self doesNotRecognizeSelector:_cmd];
}
- (void) update
{
[self doesNotRecognizeSelector:_cmd];
}
- (NSString*) stepMsg
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
@end
最後是具體的子類,不需要重新實現協議裡規定的doInit()方法,只要實現抽象類別裡的3個抽象方法就可以了:
複製代碼 代碼如下:
@interface YLSServiceDataInitScript : YLSInitialScriptTemplate
@end
複製代碼 代碼如下:
@implementation YLSServiceDataInitScript
- (void) createEverythingForFirstTime
{
// 具體邏輯
}
- (void) update
{
}
- (NSString*) stepMsg
{
// 具體邏輯
}
@end
文法沒有java裡這麼清楚,關鍵就是在抽象類別裡用
複製代碼 代碼如下:
[self doesNotRecognizeSelector:_cmd];
這行代碼實作類別似java中abstract關鍵字的效果
最後是實現調用的用戶端代碼:
複製代碼 代碼如下:
scripts = [NSMutableArray new];
// 需要執行的指令碼依次添加在下面
[scripts addObject:[[YLSShowDataInitScript new] initOrigin:self]];
[scripts addObject:[[YLSServiceDataInitScript new] initOrigin:self]];
[scripts addObject:[[YLSMemberDataInitScript new] initOrigin:self]];
[scripts addObject:[[YLSBillDataInitScript new] initOrigin:self]];
[scripts addObject:[[YLSEmployeeDataInitScript new] initOrigin:self]];
[scripts addObject:[[YLSBackupDataInitScript new] initOrigin:self]];
for (int i = 0; i < [scripts count]; i++) {
[[scripts objectAtIndex: i] doInit:clientInfo];
}