模板方法模式

101 阅读3分钟

1. 简介

模板方法模式(Template Method Pattern)是一种行为型设计模式,用于定义一类操作中的算法的框架,而将算法中的一些步骤延迟到子类中实现。模板方法模式通过定义一个抽象类来封装算法的骨架,并允许子类为其中的某些步骤提供具体实现,以实现不同的行为变体。

说人话就是,如果某类操作(操作基类)可以被分解成一系列处理步骤,但是在同类的不同操作(由操作基类衍生出来的操作子类)里面,某些步骤需要不同的处理逻辑,那么这时候就可以使用模板方法模式。

2. 结构

模板方法模式的结构相对简单,通用的UML关系如下图所示:

classDiagram
    class Client {
        +main()
    }
    
    class AbstractClass {
        <<interface>>
        +templateMethod()
        +step1()
        +step2()
        +stepN()
    }
    
    class ConcreteClass {
        +step1()
        +step2()
        +stepN()
    }
    
    AbstractClass <|.. ConcreteClass
    Client ..> ConcreteClass

除了客户端之外,模板方法模式通常包含以下几个角色:

  1. 抽象类(Abstract Class) :定义算法的抽象类,其中包含一个模板方法(Template Method)用于定义算法的框架,以及一些抽象方法(Abstract Methods)用于由子类实现的具体步骤。
  2. 具体类(Concrete Class) :继承自抽象类的具体子类,实现了抽象方法,从而提供了算法的具体实现。

3. 使用场景

模板方法模式的优点包括:

  • 提供了一种代码复用的机制,将通用的算法骨架封装在抽象类中,而具体步骤的实现可以在具体子类中进行扩展和重用。
  • 可以在不修改算法结构的情况下,通过在具体子类中重新实现具体步骤来改变算法的行为。
  • 可以更好地控制算法的执行过程,通过在模板方法中定义钩子方法(Hook Methods)来影响算法的执行流程。

模板方法模式适用于以下情况:

  • 有多个类具有相似的行为,但各个类之间的具体实现略有不同,可以通过模板方法模式来封装公共的算法骨架,并在子类中提供不同的具体实现。

4. 练习:【设计模式专题之模板方法模式】18-咖啡馆

""" 
【设计模式专题之模板方法模式】18-咖啡馆
时间限制:1.000S  空间限制:256MB
题目描述
小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。

咖啡制作过程包括以下步骤:

1. 研磨咖啡豆 Grinding coffee beans

2. 冲泡咖啡 Brewing coffee

3. 添加调料 Adding condiments

其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk

输入描述
多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。
输出描述
根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。
输入示例
1
2
输出示例
Making American Coffee:
Grinding coffee beans
Brewing coffee
Adding condiments

Making Latte:
Grinding coffee beans
Brewing coffee
Adding milk
"""
from abc import ABC, abstractmethod


class CoffeeMaker(ABC):
    def make(self):
        """ 模板方法 """
        print(f"Making {self.type}:")
        self.grind()
        self.brew()
        self.addCondiments()
        print("")
    
    def grind(self):
        print("Grinding coffee beans")
        
    def brew(self):
        print("Brewing coffee")
        
    @abstractmethod
    def addCondiments(self):
        raise NotImplemented
        
        
class AmericanCoffeeMaker(CoffeeMaker):
    def __init__(self):
        self.type = "American Coffee"
        
    def addCondiments(self):
        print("Adding condiments")
        
        
class LatteMaker(CoffeeMaker):
    def __init__(self):
        self.type = "Latte"
        
    def addCondiments(self):
        print("Adding milk")
        print("Adding condiments")
        
        
def client():
    while True:
        try:
            coffeeType = input()
        except EOFError:
            break
        else:
            if coffeeType == "1":
                maker = AmericanCoffeeMaker()
            else:
                assert coffeeType == "2"
                maker = LatteMaker()
            maker.make()
        
        
if __name__ == "__main__":
    client()

5. 参考文章

  1. 卡码网设计模式-模板方法模式
  2. refactoringguru-设计模式:模板方法模式