模版方法模式(Template Method Pattern)定义了一个算法的操作步骤,但其中的某些步骤需要派生来对应实现。
例如我们需要准备咖啡和茶,准备咖啡基本步骤为烧开水,加入咖啡粉,将咖啡倒入杯子,增加牛奶或糖(可选),准备茶的基本步骤为烧开水,加入茶粉,将茶倒入杯子,增加柠檬(可选)。我们发现在制作两个饮料的过程中,烧开水和倒入杯子这两个步骤是一样的,剩下的两个步骤,向烧开的水中增加相应的粉和增加配料,这两部分也是类似的,于是我们可以用模版方法模式,将这两步骤作为抽象方法。
代码示例
算法模版基类
咖啡因饮料模版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 28 29 30
| public abstract class CaffeineBeverage { public void PrepareRecipe() { boilWater(); brew(); pourInCup(); if (NeedCondiments()) addCondiments(); }
protected abstract void brew();
protected abstract void addCondiments();
private void boilWater() { Console.WriteLine("Boiling Water"); }
private void pourInCup() { Console.WriteLine("Pouring Water"); }
public virtual bool NeedCondiments() { return true; } }
|
例子中brew
和addCondiments
即为模版函数,而NeedCondiments
这种提供了基本实现,但派生类中仍然可以重写的函数被称为钩子(Hook
)。
咖啡因饮料实现
咖啡1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Coffee : CaffeineBeverage { protected override void addCondiments() { Console.WriteLine("Add sugar and Milk"); }
protected override void brew() { Console.WriteLine("Dripping coffee through filter"); }
public override bool NeedCondiments() { return false; } }
|
茶1 2 3 4 5 6 7 8 9 10 11 12
| class Tea : CaffeineBeverage { protected override void addCondiments() { Console.WriteLine("Adding lemon"); }
protected override void brew() { Console.WriteLine("Steeping the tea"); } }
|
测试代码及结果
测试代码1 2 3 4 5
| Coffee coffee = new Coffee(); Tea tea = new Tea(); coffee.PrepareRecipe(); Console.WriteLine(); tea.PrepareRecipe();
|
运行结果: