Design Patterns - Template Method
阿新 • • 發佈:2021-01-20
Template Method(模板方法) — 類行為型模式
定義一個操作中的演算法的骨架,而將一些步驟延遲到子類中。TemplateMethod 使得子類可以不改變一個演算法的結構即可重定義該演算法的某些特定步驟。
適用場景
- 一次性實現一個演算法的不變部分,並將可變的行為留給子類來實現。
- 各子類中公共的行為應被提取出來並集中到一個公共父類中以避免程式碼重複。也就是重分解以一般化。首先識別現有程式碼中的不同之處,並且將不同之處分離為新的操作。最後,用一個呼叫新的操作的模板方法來替換不同的程式碼。
UML 圖
效果
- 提取了類庫中公共的行為。模板方法導致一種反向的控制結構,即父類呼叫子類的操作,而不是相反。模板方法呼叫下列型別的操作:
- 具體的操作(ConcreteClass 或對客戶類的操作)
- 具體的 AbstractClass 的操作(即通常對子類有用的操作)
- 原語操作(即抽象操作)
- 鉤子操作,它提供了預設的行為,子類可以在必要時進行擴充套件,鉤子操作在預設情況下通常是空操作。
實現
幾個問題:
- 儘量減少原語操作:定義模板方法的一個重要目的是儘量減少一個子類具體實現該演算法時必須重定義的原語操作的數目。需要重定義的操作越多,客戶程式就越冗長。
- 命名約定:可以給應被重定義的操作的名字加上一個字首以識別它們。例如,用於 Macintosh 應用的 MacApp 框架給模板方法加上字首 “Do-”,如“DoCreateDocument”“DoRead”。
import abc
class Cooking(object):
"""
炒菜基類,實現了幾個抽象方法,及炒菜順序呼叫方法cook
"""
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def clean_vegetables(self, *args, **kwargs):
"""
準備蔬菜
:param args:
:param kwargs:
:return:
"""
pass
@abc.abstractmethod
def prepare_accessories(self, *args, **kwargs):
"""
準備輔料
:param args:
:param kwargs:
:return:
"""
pass
@abc.abstractmethod
def stir_fry(self, *args, **kwargs):
"""
炒菜
:param args:
:param kwargs:
:return:
"""
pass
@abc.abstractmethod
def put_flavoring(self, *args, **kwargsl):
"""
放入調味料
:param args:
:param kwargsl:
:return:
"""
pass
@abc.abstractmethod
def end_pot(self, *args, **kwargs):
"""
出鍋
:param args:
:param kwargs:
:return:
"""
pass
def cook(self):
"""
炒菜順序執行方法
:return:
"""
self.clean_vegetables().\
prepare_accessories().\
stir_fry().\
put_flavoring().\
end_pot()
class Dish_a(Cooking):
"""
(豆腐+白菜)+ (蔥+姜)+ (炒5分鐘)+(鹽+雞精)+(玻璃容器)
"""
def __init__(self):
self.dish = ""
def clean_vegetables(self):
self.dish += '白菜+豆腐' + ', '
return self
def prepare_accessories(self):
self.dish += '蔥+姜' + ', '
return self
def stir_fry(self):
self.dish += '炒5分鐘' + ', '
return self
def put_flavoring(self):
self.dish += '鹽+雞精' + ', '
return self
def end_pot(self):
self.dish += '玻璃容器' + ', '
class Dish_b(Cooking):
"""
(辣椒+肉) + (蔥+八角+姜)+ (炒10分鐘) + (鹽+十三香+味精) + (陶瓷容器)
"""
def __init__(self):
self.dish = ""
def clean_vegetables(self):
self.dish += '辣椒+肉' + ', '
return self
def prepare_accessories(self):
self.dish += '蔥+八角+姜' + ', '
return self
def stir_fry(self):
self.dish += '炒10分鐘' + ', '
return self
def put_flavoring(self):
self.dish += '鹽+十三香+味精' + ', '
return self
def end_pot(self):
self.dish += '陶瓷容器' + ', '
client
if __name__ == '__main__':
dish_a = Dish_a()
dish_b = Dish_b()
dish_a.cook()
dish_b.cook()
print('第一道菜:', dish_a.dish)
print('第二道菜:', dish_b.dish)
"""output
第一道菜: 白菜+豆腐, 蔥+姜, 炒5分鐘, 鹽+雞精, 玻璃容器,
第二道菜: 辣椒+肉, 蔥+八角+姜, 炒10分鐘, 鹽+十三香+味精, 陶瓷容器,
"""