iOS 設(shè)計(jì)模式之二十三(模板方法模式)

一、概念

1膝昆、模板方法模式的動機(jī)

? 在現(xiàn)實(shí)生活中丸边,很多事情都包含幾個相對固定的步驟,比如去公司工作荚孵,你需要先打開電腦妹窖,然后用電腦工作,最后關(guān)閉電腦回家收叶。在軟件開發(fā)中骄呼,也有類似的情況,某個方法的實(shí)現(xiàn)需要多個步驟(類似“工作”),其中有些步驟是固定的(類似“電腦開機(jī)”)蜓萄,而有些步驟并不固定(類似“具體工作”)隅茎。

? 為了提高代碼的復(fù)用性和系統(tǒng)的靈活性,可以使用一種稱之為模板方法模式的設(shè)計(jì)模式來對這類情況進(jìn)行設(shè)計(jì)嫉沽,在模板方法模式中辟犀,將實(shí)現(xiàn)功能的每一個步驟所對應(yīng)的方法稱為基本方法(比如“開機(jī)”、“具體工作”耻蛇、“關(guān)機(jī)”等)踪蹬,而調(diào)用這些基本方法同時定義基本方法的執(zhí)行次序的方法稱為模板方法(比如“在公司上班”)。

2臣咖、模板方法模式的定義

? 模板方法模式(Template Method Pattern):定義一個操作中算法的框架跃捣,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟夺蛇。

? 模板方法模式是一種基于繼承的代碼復(fù)用技術(shù)疚漆,它是一種類行為型模式

3刁赦、模板方法模式的2個角色

1)AbstractClass(抽象類):在抽象類中定義了一系列基本操作(PrimitiveOperations)娶聘,這些基本操作可以是具體的,也可以是抽象的甚脉,每一個基本操作對應(yīng)算法的一個步驟丸升,在其子類中可以重定義或?qū)崿F(xiàn)這些步驟。同時牺氨,在抽象類中實(shí)現(xiàn)了一個模板方法(Template Method)狡耻,用于定義一個算法的框架,模板方法不僅可以調(diào)用在抽象類中實(shí)現(xiàn)的基本方法猴凹,也可以調(diào)用在抽象類的子類中實(shí)現(xiàn)的基本方法夷狰,還可以調(diào)用其他對象中的方法。
2)ConcreteClass(具體子類):它是抽象類的子類郊霎,用于實(shí)現(xiàn)在父類中聲明的抽象基本操作以完成子類特定算法的步驟沼头,也可以覆蓋在父類中已經(jīng)實(shí)現(xiàn)的具體基本操作。

4书劝、模板方法與基本方法的概念

模板方法

? 一個模板方法是定義在抽象類中的进倍、把基本操作方法組合在一起形成一個總算法或一個總行為的方法。這個模板方法定義在抽象類中庄撮,并由子類不加以修改地完全繼承下來背捌。模板方法是一個具體方法,它給出了一個頂層邏輯框架洞斯,而邏輯的組成步驟在抽象類中可以是具體方法毡庆,也可以是抽象方法坑赡。由于模板方法是具體方法,因此模板方法模式中的抽象層只能是抽象類么抗,而不是接口毅否。

基本方法

基本方法是實(shí)現(xiàn)算法各個步驟的方法,是模板方法的組成部分蝇刀∶樱基本方法又可以分為三種:

1)抽象方法(Abstract Method):一個抽象方法由抽象類聲明、由其具體子類實(shí)現(xiàn)吞琐。在C#和Java語言里一個抽象方法以abstract關(guān)鍵字標(biāo)識捆探。

2)具體方法(Concrete Method):一個具體方法由一個抽象類或具體類聲明并實(shí)現(xiàn),其子類可以進(jìn)行覆蓋也可以直接繼承站粟。

3)鉤子方法(Hook Method):一個鉤子方法由一個抽象類或具體類聲明并實(shí)現(xiàn)黍图,而其子類可能會加以擴(kuò)展。鉤子方法分兩類:第一類鉤子方法可以與一些具體步驟“掛鉤”奴烙,以實(shí)現(xiàn)在不同條件下執(zhí)行模板方法中的不同步驟助被,這類鉤子方法的返回類型通常是bool類型的,這類方法名一般為IsXXX()切诀;第二類鉤子方法就是實(shí)現(xiàn)體為空的具體方法揩环,這類鉤子方法的好處在于子類如果沒有覆蓋父類中定義的鉤子方法,編譯可以正常通過幅虑。

5丰滑、結(jié)構(gòu)圖
模板方法模式

二、示例

? 在模板方法模式中倒庵,由于面向?qū)ο蟮亩鄳B(tài)性吨枉,子類對象在運(yùn)行時將覆蓋父類對象,子類中定義的方法也將覆蓋父類中定義的方法哄芜。因此程序在運(yùn)行時,子類的鉤子方法也將覆蓋父類的鉤子方法柬唯,從而可以通過在子類中實(shí)現(xiàn)的鉤子方法對父類方法的執(zhí)行進(jìn)行約束认臊,實(shí)現(xiàn)子類對父類行為的反向控制。

? 本Demo以程序員工作為例:

1)先創(chuàng)建一個Coder類锄奢,類中有模板方法和一系列基本方法失晴,表示抽象類;

2)然后創(chuàng)建Employee類和Leader類拘央,都繼承自Coder類涂屁,表示具體子類。

具體代碼如下:

Coder類:

// 程序猿:抽象類
@interface Coder : NSObject
- (void)work; //模板方法
- (void)startComputer; //具體方法
- (void)coding; //抽象方法灰伟,OC沒有abstract這個關(guān)鍵字拆又,這里選擇不實(shí)現(xiàn)方法
- (void)closeComputer; //具體方法
- (BOOL)isNeedCloseComputer; //鉤子方法
@end

@implementation Coder
- (void)work {
    [self startComputer];
    [self coding];
    if ([self isNeedCloseComputer]) {
        [self closeComputer];
    }
}

- (void)startComputer {
    NSLog(@"電腦開機(jī)");
}

- (void)closeComputer {
    NSLog(@"電腦關(guān)機(jī)");
}

- (BOOL)isNeedCloseComputer {
    NSLog(@"Windows電腦需要關(guān)機(jī)");
    return YES;
}
@end

Employee類和Leader類:

// Employee 普通員工類
@interface Employee : Coder
@end
@implementation Employee
- (void)coding { // 實(shí)現(xiàn)抽象方法
    NSLog(@"程序猿努力敲代碼");
}
@end

// Leader 領(lǐng)導(dǎo)類
@interface Leader : Coder
@end
@implementation Leader
- (void)coding { // 實(shí)現(xiàn)抽象方法
    NSLog(@"領(lǐng)導(dǎo)指揮大家敲代碼");
}

- (BOOL)isNeedCloseComputer { // 重寫鉤子方法
    NSLog(@"MacBook Pro不需要關(guān)機(jī)");
    return NO;
}
@end

運(yùn)行代碼:

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Employee *employee = [Employee new];
    [employee work];
    NSLog(@"---------------------");
    
    Leader *leader = [Leader new];
    [leader work];
}

打印結(jié)果:

電腦開機(jī)
程序猿努力敲代碼
Windows電腦需要關(guān)機(jī)
電腦關(guān)機(jī)
---------------------
電腦開機(jī)
領(lǐng)導(dǎo)指揮大家敲代碼
MacBook Pro不需要關(guān)機(jī)

三儒旬、總結(jié)

? 模板方法模式是基于繼承的代碼復(fù)用技術(shù),廣泛應(yīng)用于框架設(shè)計(jì)中帖族,以確保通過父類來控制處理流程的邏輯順序(如框架的初始化栈源,測試流程的設(shè)置等)。

1竖般、優(yōu)點(diǎn)

1甚垦、在父類中形式化地定義一個算法,而由它的子類來實(shí)現(xiàn)細(xì)節(jié)的處理涣雕,在子類實(shí)現(xiàn)詳細(xì)的處理算法時并不會改變算法中步驟的執(zhí)行次序艰亮。

2、模板方法模式是一種代碼復(fù)用技術(shù)挣郭,它在類庫設(shè)計(jì)中尤為重要迄埃,它提取了類庫中的公共行為,將公共行為放在父類中丈屹,而通過其子類來實(shí)現(xiàn)不同的行為调俘,它鼓勵我們恰當(dāng)使用繼承來實(shí)現(xiàn)代碼復(fù)用。

3旺垒、可實(shí)現(xiàn)一種反向控制結(jié)構(gòu)彩库,通過子類覆蓋父類的鉤子方法來決定某一特定步驟是否需要執(zhí)行。

4先蒋、在模板方法模式中可以通過子類來覆蓋父類的基本方法骇钦,不同的子類可以提供基本方法的不同實(shí)現(xiàn),更換和增加新的子類很方便竞漾,符合單一職責(zé)原則和開閉原則眯搭。

2、缺點(diǎn)

? 需要為每一個基本方法的不同實(shí)現(xiàn)提供一個子類业岁,如果父類中可變的基本方法太多鳞仙,將會導(dǎo)致類的個數(shù)增加,系統(tǒng)更加龐大笔时,設(shè)計(jì)也更加抽象棍好,此時,可結(jié)合橋接模式來進(jìn)行設(shè)計(jì)。

3、適用場景

1拓巧、對一些復(fù)雜的算法進(jìn)行分割盗迟,將其算法中固定不變的部分設(shè)計(jì)為模板方法和父類具體方法,而一些可以改變的細(xì)節(jié)由其子類來實(shí)現(xiàn)。即:一次性實(shí)現(xiàn)一個算法的不變部分,并將可變的行為留給子類來實(shí)現(xiàn)。

2低散、各子類中公共的行為應(yīng)被提取出來并集中到一個公共父類中以避免代碼重復(fù)俯邓。

3、需要通過子類來決定父類算法中某個步驟是否執(zhí)行谦纱,實(shí)現(xiàn)子類對父類的反向控制看成。

4、iOS應(yīng)用舉例

? 在Cocoa Touch框架中跨嘉,最常見的UIViewController川慌,如果需要適配屏幕旋轉(zhuǎn),那么必須重寫各種旋轉(zhuǎn)的方法祠乃,比如shouldAutorotate就是典型的鉤子方法梦重。還有UIView有個drawRect方法,如果需要執(zhí)行定制繪圖亮瓷,那么子類可以重寫這個方法來達(dá)到效果琴拧,drawRect也是鉤子方法。

Demo地址:iOS-Design-Patterns

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘱支,一起剝皮案震驚了整個濱河市蚓胸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌除师,老刑警劉巖沛膳,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異汛聚,居然都是意外死亡锹安,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門倚舀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來叹哭,“玉大人,你說我怎么就攤上這事痕貌》缯郑” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵舵稠,是天一觀的道長泊交。 經(jīng)常有香客問我,道長柱查,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任云石,我火速辦了婚禮唉工,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汹忠。我一直安慰自己淋硝,他們只是感情好雹熬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谣膳,像睡著了一般竿报。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上继谚,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天烈菌,我揣著相機(jī)與錄音,去河邊找鬼花履。 笑死芽世,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的诡壁。 我是一名探鬼主播济瓢,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妹卿!你這毒婦竟也來了旺矾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤夺克,失蹤者是張志新(化名)和其女友劉穎箕宙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體懊直,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扒吁,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了室囊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片雕崩。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖融撞,靈堂內(nèi)的尸體忽然破棺而出盼铁,到底是詐尸還是另有隱情,我是刑警寧澤尝偎,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布饶火,位于F島的核電站,受9級特大地震影響致扯,放射性物質(zhì)發(fā)生泄漏肤寝。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一抖僵、第九天 我趴在偏房一處隱蔽的房頂上張望鲤看。 院中可真熱鬧,春花似錦耍群、人聲如沸义桂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慷吊。三九已至袖裕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溉瓶,已是汗流浹背急鳄。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嚷闭,地道東北人攒岛。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像胞锰,于是被迫代替她去往敵國和親灾锯。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容