Python 设计模式——模板方法模式

行为模式主要关注对象的响应性,处理对象之间的交互以实现更强大的功能。模板方法模式即为一种行为设计模式。
比如可以将制作饮料的步骤定义为模板方法中的算法,子类就能使用模板方法来实现沏茶的步骤。且步骤的改变(即子类的具体实现)并不会影响原始算法的结构。这样模板方法模式中的子类就可以通过覆盖来创建不同的行为。

模板方法模式适用于以下场景:

  • 当多个算法或类实现类似或相同逻辑的时候
  • 在子类中实现算法有助于减少重复代码的时候
  • 子类可以通过覆盖实现多种不同行为的时候

模板方法模式的主要意图:

  • 使用基本操作定义算法的框架
  • 重新定义子类的某些操作,无需修改算法的结构
  • 实现代码重用并避免重复工作
  • 利用通用接口或功能实现

UML

  • AbstractClass:在抽象方法的帮助下定义算法的操作或步骤。这些步骤将被具体的子类覆盖
  • template_method():定义算法的框架。在模板方法中调用抽象方法定义的步骤以形成序列或算法
  • ConcreteClass:实现需要算法子类关注的特定步骤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
from abc import ABCMeta, abstractmethod

class Compiler(metaclass=ABCMeta):
@abstractmethod
def collectSource(self):
pass

@abstractmethod
def compileToObject(self):
pass

@abstractmethod
def run(self):
pass

def compileAndRun(self):
self.collectSource()
self.compileToObject()
self.run()


class iOSCompiler(Compiler):
def collectSource(self):
print("Collecting Swift Source Code")

def compileToObject(self):
print("Compiling Swift code to LLVM bitcode")

def run(self):
print("Program runing on runtime environment")


iOS = iOSCompiler()
iOS.compileAndRun()
# => Collecting Swift Source Code
# => Compiling Swift code to LLVM bitcode
# => Program runing on runtime environment

现实中的模板方法模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
from abc import abstractmethod, ABCMeta

class Trip(metaclass=ABCMeta):
@abstractmethod
def setTransport(self):
pass

@abstractmethod
def day1(self):
pass

@abstractmethod
def day2(self):
pass

@abstractmethod
def day3(self):
pass

@abstractmethod
def returnHome(self):
pass

def itinerary(self):
self.setTransport()
self.day1()
self.day2()
self.day3()
self.returnHome()


class VeniceTrip(Trip):
def setTransport(self):
print("Take a boat and find your way in the Grand Canal")

def day1(self):
print("Visit St Mark's Basilica in St Mark's Square")

def day2(self):
print("Appreciate Doge's Palace")

def day3(self):
print("Enjoy the food near the Rialto Bridge")

def returnHome(self):
print("Get souovenirs for friends and get back")


class MaldivesTrip(Trip):
def setTransport(self):
print("On foot, on any island, Wow!")

def day1(self):
print("Enjoy the marine life of Banana Reef")

def day2(self):
print("Go for the water sports and snorkelling")

def day3(self):
print("Relax on the beach and enjoy the sun")

def returnHome(self):
print("Don't feel like leaving the beach..")


class TravelAgency:
def arrange_trip(self):
choice = input("What kind of place you'd like to go historical or to a beach? ")
if choice == 'historical':
self.trip = VeniceTrip()
self.trip.itinerary()
if choice == 'beach':
self.trip = MaldivesTrip()
self.trip.itinerary()


TravelAgency().arrange_trip()

# => What kind of place you'd like to go historical or to a beach? beach
# => On foot, on any island, Wow!
# => Enjoy the marine life of Banana Reef
# => Go for the water sports and snorkelling
# => Relax on the beach and enjoy the sun
# => Don't feel like leaving the beach..
  • 抽象类 Trip 是一个接口,定义了不同日子使用的交通方式和参观地点等细节
  • setTransport 是一个抽象方法,由 ConcreteClass 实现,作用是设置交通方式
  • day1()、day2()、day3() 抽象方法定义了特定日期所参观的地点
  • itinerary() 模板方法则用于创建完整的行程
  • VeniceTrip 类和 MaldivesTrip 类是 Trip 接口的具体实现

模板方法的优点和缺点

优点:

  • 没有代码重复
  • 使用继承而不是合成,只有为数不多的几个方法需要重写
  • 灵活性,允许子类决定如何实现算法中的步骤

缺点:

  • 调试和理解模板方法模式中的流程序列时可能会令人困惑
  • 模板框架的维护可能是一个问题,任何层次(底层或高层)的变更都可能对实现造成干扰