1. 模板模式(Template)介绍
UML类图
角色介绍
- 抽象方法:父类中只声明但不加以实现,而是定义好规范,然后由它的子类去实现。
- 模版方法:由抽象类声明并加以实现。一般来说,模版方法调用抽象方法来完成主要的逻辑功能,并且,模版方法大多会定义为final类型,指明主要的逻辑功能在子类中不能被重写。
- 钩子方法:由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。
抽象类的任务是搭建逻辑的框架,通常由经验丰富的人员编写,因为抽象类的好坏直接决定了程序是否稳定性。
用途
定义一个操作中算法的框架,而将一些步骤延迟到子类中,使得子类可以不改变算法的结构即可重定义该算法中的某些特定步骤。
模版方法的优点及适用场景
容易扩展。一般来说,抽象类中的模版方法是不易反生改变的部分,而抽象方法是容易反生变化的部分,因此通过增加实现类一般可以很容易实现功能的扩展,符合开闭原则。
便于维护。对于模版方法模式来说,正是由于他们的主要逻辑相同,才使用了模版方法,假如不使用模版方法,任由这些相同的代码散乱的分布在不同的类中,维护起来是非常不方便的。
比较灵活。因为有钩子方法,因此,子类的实现也可以影响父类中主逻辑的运行。但是,在灵活的同时,由于子类影响到了父类,违反了里氏替换原则,也会给程序带来风险。这就对抽象类的设计有了更高的要求。
在多个子类拥有相同的方法,并且这些方法逻辑相同时,可以考虑使用模版方法模式。在程序的主框架相同,细节不同的场合下,也比较适合使用这种模式。
2. 示例
- 某日,程序员A拿到一个任务:给定一个整数数组,把数组中的数由小到大排序,然后把排序之后的结果打印出来。经过分析之后,这个任务大体上可分为两部分,排序和打印,打印功能好实现,排序就有点麻烦了。但是A有办法,先把打印功能完成,排序功能另找人做。
- 写完后,A找到刚毕业入职不久的同事B说:有个任务,主要逻辑我已经写好了,你把剩下的逻辑实现一下吧。于是把AbstractSort类给B,让B写实现。
"""Template Pattern with Python Code
"""
from abc import abstractmethod, ABCMeta
class AbstractSort(metaclass=ABCMeta):
"""将数组array由小到大排序
@param array
"""
@abstractmethod
def sort(self, array):
pass
def show_sort_result(self, array):
self.sort(array);
print("排序结果:");
for i in range(len(array)):
print("%3s" % array[i])
class ConcreteSort(AbstractSort):
def _select_sort(self, array, index):
MinValue = 32767 # 最小值变量
indexMin = 0 # 最小值索引变量
for i in range(index, len(array)):
if array[i] < MinValue: # 找到最小值
MinValue = array[i] # 储存最小值
indexMin = i
Temp = array[index] # 交换两数值
array[index] = array[indexMin]
array[indexMin] = Temp
def sort(self, array):
for i in range(len(array)):
self._select_sort(array, i)
class Client(object):
def main(self):
a = [10, 32, 1, 9, 5, 7, 12, 0, 4, 3] # 预设数据数组
s = ConcreteSort()
s.show_sort_result(a)
if __name__ == "__main__":
Client().main()
输出:
# ./Template.py
排序结果:
0
1
3
4
5
7
9
10
12
32
参考:
https://wiki.jikexueyuan.com/project/java-design-pattern/template-method-pattern.html