模板方法模式——封装算法

目录

在面向对象里面的封装特性中,我们可以利用工厂模式封装对象创建利用命令模式封装方法调用(命令请求),用适配器模式和外观模式封装复杂接口和复杂子系统。现在讨论用模板方法模式封装算法

1 模板方法模式

代模板方法模式一个方法中定义一个算法的骨架,而将算法的一些步骤延迟到子类去实现。模板方法使得子类在不改变算法结构的情况下,重新定义算法的某些步骤

  • 这个模式创建一个算法的模板,而模板就是一个抽象类的一个方法
  • 这个方法将算法定义成一组步骤。其中的步骤可以是抽象的由具体子类来实现各个子类的该步骤的不同实现;也可以是一个钩子,由具体子类选择继承抽象类的该步骤或者重新覆盖该步骤

2 模板方法模式的UML类图

在这里插入图片描述

  • AbstractClass:抽象类。定义了模板方法和执行算法的一组方法步骤,该步骤可以是抽象的,由子类来实现;也可以是一个钩子方法,由子类选择性地钩取抽象类该步骤的实现重新覆盖该钩子方法
  • templateMethod:模板方法。封装了执行算法的一种步骤,这些步骤必须在抽象类中有声明,当不一定实现。这样就使得模板方法本身和具体的步骤实现解耦,因为具体的步骤实现在子类中完成
  • ConcreteClass:具体子类。实现了抽象类中定义的的抽象方法选择性地继承抽象类钩子的实现重新覆盖该钩子方法

3 模板方法模式的一个例子:要caffe还是tea

制作caffe和tea的步骤大同小异,都是先将水煮开,用热水泡caffe或者tea,然后将饮料倒进杯子,最后加一些适当的调料。只是第二步用热水泡caffe或者tea的方式可能不一样,第四步加的调料可能不同。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4 好莱坞准则和模板方法模式

4.1 好莱坞准则

别调用(打电话给)我们,我们会调用(打电话给)你。

  • 防止“依赖腐败”:底层组件依赖高层组件,而高层组件又依赖底层组件。
  • 在好莱坞准则下,底层组件将自己挂钩到系统上,高层组件决定什么时候调用底层组件。高层组件对底层组件的方式是“别调用我们,我们会调用了你”。这在计算机的分层框架中经常使用。
  • 工厂方法模式,观察者模式都利用了好莱坞准则。

4.2 好莱坞准则与模板方法

在这里插入图片描述

5 模板方法模式的一个Python实现例子

5.1 例子解释

假如你要通过旅行社去旅游,旅行社提供了不同的套餐让你选择。不同的套餐中都定制出行方式,每天的行程安排。具体的出行方式和行程安排由具体套餐决定。

5.2 UML类图

在这里插入图片描述

5.3 代码实现

  • 抽象类Trip
    • 抽象类,为具体子类提供了一个接口,可以定义了具体方法、抽象方法和钩子
    • 抽象方法setTransport()、day1()、day2()、day3()、returnHome()由具体子类实现
    • 模板方法itinerary()封装的算法步骤依赖抽象方法setTransport()、day1()、day2()、day3()、returnHome()
from abc import ABCMeta, abstractmethod

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()
  • 具体类VeniceTrip和MaldivesTrip
    • 各个具体类实现了抽象类中的抽象方法,根据具体类的不同,采用不同的旅行套餐
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 souvenirs 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("Dont feel like leaving the beach")
    
  • 客户类TravelAgency
    • arrange_trip()方法根据客户的输入选择历史旅行还是沙滩旅行,再根据客户的选择实例化相应的类,然后调用相应类的模板方法itinerary()
class TravelAgency:
    '''
    Client类
    '''
    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()
        elif choice == 'beach':
            self.trip = MaldivesTrip()
            self.trip.itinerary()
  • 客户端
    • 客户端实例化一个客户对象然后调用客户对象的arrange_trip()方法
    • 在arrange_trip()方法中根据客户的输入选择历史旅行还是沙滩旅行,再根据客户的选择实例化相应的类,然后调用相应类的模板方法itinerary()
if __name__ == '__main__':
   travelAgency = TravelAgency()
   travelAgency.arrange_trip()
    

5.4 输出结果

在这里插入图片描述
在这里插入图片描述
总结:

  • 模板方法定义了算法步骤接口,这些步骤的实现延迟到子类中将模板方法与具体子类的方法的实现解耦,是一种最重要的代码复用技术。
  • 抽象类可以定义了具体方法、抽象方法和钩子
  • 钩子方法在抽象类中不做事或者只做默认的事子类可以选择要不要覆盖它
  • 为了防止子类改变模板方法中的算法,可以将模板方法声明为final
  • 好莱坞准则:将决策权放在高级层模块中,在高级层模块中调用底层模块
    -策略模式使用组合封装整个算法及各个组件框架,而模板方法模式使用继承封装算法步骤
  • 工厂方法是一种特殊的模板方法,用于封装对象创建。

github地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值