一、定义模板方法模式
1.场景:
1.1 当多个算法或类实现类似或相同逻辑的时候。
1.2 在子类中实现算法有助于减少重复代码的时候。
1.3 可以让子类利用覆盖实现行为来定义多个算法的时候。
2.目的:
2.1 使用基本操作定义算法的框架。
2.2 重新定义子类的某些操作,而无需修改算法的结构。
2.3 实现代码重用并避免重复工作
2.4 利用通用接口或实现
3.模板方法UML类图
3.1 AbstractClass : 在抽象方法的帮助下定义算法的操作或步骤。这些步骤将被具体子类覆盖。
3.2 tmplate_method():定义算法的框架。在模板方法中调用抽象方法定义的多个步骤来定义序列或算法本身。
3.3 ConcreteClass:实现(由抽象方法定义的)步骤,来执行算法子类的特定步骤。
3.4 代码
# -*- coding: UTF-8 -*-
from abc import ABCMeta,abstractmethod
# 抽象方法 AbstractClass
class AbstractClass():
def __init__(self):
pass
@abstractmethod
def operation1(self):
pass
@abstractmethod
def operation2(self):
pass
# 模板方法 tmplate_method()
def template_method(self):
print ("Defining the Algorithm.Operation1 follows Operation2")
self.operation2()
self.operation1()
# 具体类 ConcreteClass
class ConcreteClass(AbstractClass):
def operation1(self):
print ("My Concrete Operation1")
def operation2(self):
print ("Operation 2 remains same")
# 客户端
class Client:
def mian(self):
self.concreate = ConcreteClass()
self.concreate.template_method()
client = Client()
client.mian()
二、现实世界中的模板方法模式
1.案例:旅行社安排出游
# -*- coding: UTF-8 -*-
from abc import ABCMeta,abstractmethod
# 抽象方法 Trip
class Trip():
def __init__(self):
pass
@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
# 模板方法 tmplate_method()
def itinerary(self):
self.setTransport()
self.day1()
self.day2()
self.day3()
self.returnHome()
# 具体类 VeniceTrip
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 Basilica in St Mark Square")
def day2(self):
print ("Enjoy the food near the Rialto Bridge")
def day3(self):
print ("Get souvenirs for friends and get back")
def returnHome(self):
print ("Get souvenirs for friends and get back")
# 具体类 MaldivesTrip
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 ("Dont feel like leaving the beach..")
# 客户端
class TravelAgency:
def arrange_trip(self):
choice =raw_input("What kind of place you 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()
三、模板方法模式-钩子
1.1 钩子是在抽象类中声明的方法,它通常被赋予一个默认实现。
1.2 通常情况下,当子类必须提供实现时,我们会使用抽象方法,并且当子类的实现不是强制的时候,我们就会使用钩子。
四、好莱坞原则与模板方法
1.1 好莱坞原则:不要给我们打电话,我们会打给你。好莱坞哲学:如果有合适演员的角色,影棚会给演员打电话。
1.2 面向对象中的好莱坞原则:允许底层组件使用好莱坞原则将自己挂入系统中,高层组件确定底层系统的使用方式,以及何时需要他们。
五、模板方法模式的优点和缺点
优点:
1.1 代码没有重复
1.2 模板方法用的继承而非合成,代码可以重用。
1.3 灵活性允许子类决定如何实现算法中的步骤。
缺点:
2.1 调试和理解模板方法中的流程序列有时会令人困惑。
2.2 维护难度大
六、常见问题解答
1.1 是否应该禁止底层组件调用更高层组件中的方法:
不,底层组件当然通过继承来调用高层组件。然而,程序员需要注意的是,不要出现循环依赖性,即高层组件和底层组件彼此依赖。
1.2 策略模式是否类似于模板模式?
模板取决于继承,而策略使用组合。模板方法模式是通过子类化在编译时进行算法选择,而策略模式是运行时进行选择。
本系列项目代码地址:Python-design-pattern