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
除了客户端之外,模板方法模式通常包含以下几个角色:
- 抽象类(Abstract Class) :定义算法的抽象类,其中包含一个模板方法(Template Method)用于定义算法的框架,以及一些抽象方法(Abstract Methods)用于由子类实现的具体步骤。
- 具体类(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()