Template Method
动机(Motivation)
- 在软件构建过程中,对于某一项任务,它常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而无法和任务的整体结构同时实现。
- 如何在确定稳定操作结构的前提下,来灵活应对各个子步骤的变化或者晚期实现需求?
模式定义
定义一个操作中的算法的骨架 (稳定) ,而将一些步骤延迟 (变化) 到子类中。
Template Method使得子类可以不改变(复用)一个算法的结构即可重定义(override 重写)该算法的
某些特定步骤。
——《 设计模式》 GoF
要点总结
- Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
- 除了可以灵活应对子步骤的变化外, “不要调用我,让我来调用你” 的反向控制结构是Template Method的典型应用。
- 在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将它们设置为protected方法。
例子
一般实现
# -*- coding:utf-8 -*-
class Library(object):
# 框架开发者
def step1(self):
print('step1')
def step3(self):
print('step3')
def step5(self):
print('step5')
class Application(object):
# 应用开发者
def step2(self):
print('step2')
return True
def step4(self):
print('step4')
def run_app():
lib = Library()
app = Application()
lib.step1()
if app.step2():
lib.step3()
for i in range(3):
app.step4()
lib.step5()
if __name__ == '__main__':
run_app()
模板模式
# -*- coding:utf-8 -*-
class Library(object):
# 框架开发者
def step1(self):
print('step1')
def step3(self):
print('step3')
def step5(self):
print('step5')
def run_app(self):
self.step1()
if self.step2():
self.step3()
for i in range(3):
self.step4()
self.step5()
def step2(self):
# 需要子类重写
pass
def step4(self):
# 需要子类重写
pass
class Application(Library):
# 应用开发者
def step2(self):
print('step2')
return True
def step4(self):
print('step4')
class Application2(Library):
# 应用开发者
def step2(self):
print('Application2 step2')
return False
def step4(self):
print('Application2 step4')
if __name__ == '__main__':
app = Application()
app.run_app()
print('-'*10)
app2 = Application2()
app2.run_app()
- 代码中,调用的整个流程
run_app
是稳定的,而step2
和step4
是变化的。 - 第一个实现版本中,将
run_app
交给应用开发者来写,一是冗余,二是容易写错。而 模板方法 在基类中实现整个算法的骨架 (稳定) ,而将一些步骤延迟 (变化) 到子类。 - 例子中 模板方法 减轻了应用开发者的负担,且增加了代码的可扩展性和稳定性。