模版方法模式入门

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

在以下情形下,应该考虑使用模板方法:

  • 需要一次性实现算法的不变部分,并将可变的行为留给子类来实现
  • 子类的共同行为应该被提取出来放到公共类中,避免代码重复。现有代码的差别应该被分离为新的操作。然后用一个调用这些新操作的模板方法来替换这些不同的代码
  • 需要控制子类的扩展。可以定义一个在特定点调用”钩子(hook)”操作的模板方法。子类可以通过对hook操作的实现在这些点扩展功能

UML类图

代码示例

定义模板基类:

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
class CaffeineBeverage {
//模板方法
final func prepareRecipe() {
boilWater()
brew()
pourInCup()
if hook() {
addCondiments()
}
}
private final func boilWater() {
print("Boiling Water...")
}
private final func pourInCup() {
print("Pour into cup")
}

// 具体冲泡方法由子类决定
fileprivate func brew() {}
fileprivate func addCondiments() {}

//hook方法,能让子类在指定点进行功能扩展,这里让子类控制是否需要添加辅料
fileprivate func hook() -> Bool {
return false
}
}

具体的子类实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Coffee: CaffeineBeverage {
fileprivate override func brew() {
print("Dripping Coffee through filter")
}
fileprivate override func addCondiments() {
print("Add Sugar and Milk")
}
fileprivate override func hook() -> Bool {
return true
}
}

class Tea: CaffeineBeverage {
fileprivate override func brew() {
print("Steeping the tea")
}
fileprivate override func addCondiments() {
print("Add Lemon")
}
fileprivate override func hook() -> Bool {
return false
}
}

客户端调用:

1
2
3
4
5
let tea = Tea()
tea.prepareRecipe()

let coffee = Coffee()
coffee.prepareRecipe()

代码执行结果:

1
2
3
4
5
6
7
Boiling Water...
Steeping the tea
Pour into cup
Boiling Water...
Dripping Coffee through filter
Pour into cup
Add Sugar and Milk