思想:一般只將統(tǒng)一的方法(如下面例子中的“驗證”)在父類中實(shí)現(xiàn)抛人,而將可變的方法(“登錄、注冊”)交給子類來實(shí)現(xiàn),在子類實(shí)例中可以調(diào)用父類的方法‘“驗證”來驗證子類的“登錄、注冊”)骡湖。
意圖:
定義一個操作中的算法的骨架,而將一些步驟延遲到子類中峻厚。
TemplateMethod 使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟响蕴。
適用性:
一次性實(shí)現(xiàn)一個算法的不變的部分,并將可變的行為留給子類來實(shí)現(xiàn)惠桃。
各子類中公共的行為應(yīng)被提取出來并集中到一個公共父類中以避免代碼重復(fù)浦夷。
控制子類擴(kuò)展。模板方法只在特定點(diǎn)調(diào)用“hook ”操作刽射,這樣就只允許在這些點(diǎn)進(jìn)行擴(kuò)展军拟。
模板方法模式概述
在現(xiàn)實(shí)生活中,很多事情都包含幾個實(shí)現(xiàn)步驟誓禁,例如請客吃飯,無論吃什么肾档,一般都包含點(diǎn)單摹恰、吃東西、買單等幾個步驟怒见,通常情況下這幾個步驟的次序是:點(diǎn)單 --> 吃東西 --> 買單俗慈。在這三個步驟中,點(diǎn)單和買單大同小異遣耍,最大的區(qū)別在于第二步——吃什么闺阱?吃面條和吃滿漢全席可大不相同,如圖1所示:
圖1 請客吃飯示意圖
在軟件開發(fā)中舵变,有時也會遇到類似的情況酣溃,某個方法的實(shí)現(xiàn)需要多個步驟(類似“請客”),其中有些步驟是固定的(類似“點(diǎn)單”和“買單”)纪隙,而有些步驟并不固定赊豌,存在可變性(類似“吃東西”)。為了提高代碼的復(fù)用性和系統(tǒng)的靈活性绵咱,可以使用一種稱之為模板方法模式的設(shè)計模式來對這類情況進(jìn)行設(shè)計碘饼,在模板方法模式中,將實(shí)現(xiàn)功能的每一個步驟所對應(yīng)的方法稱為基本方法(例如“點(diǎn)單”、“吃東西”和“買單”)艾恼,而調(diào)用這些基本方法同時定義基本方法的執(zhí)行次序的方法稱為模板方法(例如“請客”)住涉。在模板方法模式中,可以將相同的代碼放在父類中钠绍,例如將模板方法“請客”以及基本方法“點(diǎn)單”和“買單”的實(shí)現(xiàn)放在父類中秆吵,而對于基本方法“吃東西”,在父類中只做一個聲明五慈,將其具體實(shí)現(xiàn)放在不同的子類中纳寂,在一個子類中提供“吃面條”的實(shí)現(xiàn),而另一個子類提供“吃滿漢全席”的實(shí)現(xiàn)泻拦。通過使用模板方法模式毙芜,一方面提高了代碼的復(fù)用性,另一方面還可以利用面向?qū)ο蟮亩鄳B(tài)性争拐,在運(yùn)行時選擇一種具體子類腋粥,實(shí)現(xiàn)完整的“請客”方法,提高系統(tǒng)的靈活性和可擴(kuò)展性架曹。
模板方法模式定義如下:
模板方法模式:定義一個操作中算法的框架隘冲,而將一些步驟延遲到子類中。模板方法模式使得子類可以不改變一個算法的結(jié)構(gòu)即可重定義該算法的某些特定步驟绑雄。
Template Method Pattern: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.
模板方法模式是一種基于繼承的代碼復(fù)用技術(shù)展辞,它是一種類行為型模式。
模板方法模式是結(jié)構(gòu)最簡單的行為型設(shè)計模式万牺,在其結(jié)構(gòu)中只存在父類與子類之間的繼承關(guān)系罗珍。通過使用模板方法模式,可以將一些復(fù)雜流程的實(shí)現(xiàn)步驟封裝在一系列基本方法中脚粟,在抽象父類中提供一個稱之為模板方法的方法來定義這些基本方法的執(zhí)行次序覆旱,而通過其子類來覆蓋某些步驟,從而使得相同的算法框架可以有不同的執(zhí)行結(jié)果核无。模板方法模式提供了一個模板方法來定義算法框架扣唱,而某些具體步驟的實(shí)現(xiàn)可以在其子類中完成。
案例一
#_*_coding:utf-8_*_
class Register(object):
'''用戶注冊接口'''
def register(self):
pass
def login(self):
pass
def auth(self):
self.register()
self.login()
class RegisterByQQ(Register):
'''qq注冊'''
def register(self):
print("---用qq注冊-----")
def login(self):
print('----用qq登錄-----')
class RegisterByWeiChat(Register):
'''微信注冊'''
def register(self):
print("---用微信注冊-----")
def login(self):
print('----用微信登錄-----')
if __name__ == "__main__":
register1 = RegisterByQQ()
register1.login()
register1.auth()
register2 = RegisterByWeiChat()
register2.login()
register2.auth()
運(yùn)行結(jié)果
'''
----用qq登錄-----
---用qq注冊-----
----用qq登錄-----
----用微信登錄-----
---用微信注冊-----
----用微信登錄-----
'''