模版方法模式在一个方法中定义一个算法的骨架,而将一些具体步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
在以下情形下,应该考虑使用模板方法:
- 需要一次性实现算法的不变部分,并将可变的行为留给子类来实现
- 子类的共同行为应该被提取出来放到公共类中,避免代码重复。现有代码的差别应该被分离为新的操作。然后用一个调用这些新操作的模板方法来替换这些不同的代码
- 需要控制子类的扩展。可以定义一个在特定点调用”钩子(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 27
| 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 24
| 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 8
| Boiling Water... Steeping the tea Pour into cup Boiling Water... Dripping Coffee through filter Pour into cup Add Sugar and Milk
|