模板方法模式(Template Method Pattern)
一、什么是模板方法模式
摸板方法(Template Method)模式是一种非常简单而又经常使用的设计模式.先创建一个父类,把其中的一个或多个方法留给子类去实现,这实际上就是在使用摸板模式.所谓的摸板模式可以这样来理解:"在一个类中定义一个算法,但将此算法的某些细节留到子类中去实现.换句话说,基类是一个抽象类,那么你就是在使用一种简单形式的摸板模式."
意图:
定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
结构图:
结构与参与者:
抽象模板角色
- 定义了一个或多个抽象操作,以便让子类实现。
- 定义并实现了一个摸板方法。
具体摸板角色
- 实现父类所定义的一个或多个抽象方法。
- 每一个抽象摸板角色都可以有任意多个具体摸板角色与之对应。
- 每一个具体摸板角色都可以给出这些抽象方法的不同实现。
二、模板方法模式的种类
- 抽象模板角色里提供完整的方法,它完成了所有派生类都要用到的一些基本功能。
- 抽象模板角色里只提供空方法,把功能全部留给派生类去实现。
- 抽象模板角色里只包含某些操作的默认实现,派生类里可以重新定义这些方法的实现。
- 抽象模板角色里模板方法,他是一个调用抽象方法,钩子方法以及具体方法的各种组合。
三、模板方法模式的应用实例
先来看一张图:
不用我说,大家都知道,一台电脑(参考上图)的基本组成部分包括的硬件主要有CPU,主板,硬盘,显卡以及内存等.OK,现在的需求就是要去造一台电脑,可计算机生产商有没给我们提供生产电脑的方法(MackPC)呢?没有吧,那么我们自己来定义一个总可以吧(听起好象有点夸张,呵呵,怎么生产电脑的方法也可以自己定义了,那不是自己就可以生产电脑了,可不是呢,这里只是定义了一个生产电脑的程序方法罢).OK,Go!
1、定义一个抽象模板角色,个人电脑的模板
1 // 抽象摸板角色 2 // 定义了一个或多个抽象操作,以便让子类实现。 3 // 定义并实现了一个模板方法。 4 public abstract class PCTemplate 5 { 6 private string pcType; 7 8 public PCTemplate(string pcType) 9 { 10 this.pcType = pcType; 11 } 12 13 //留给子类去实现(抽象操作) 14 protected abstract void MakeCPU(string pcType); 15 protected abstract void MakeRAM(string pcType); 16 protected abstract void MakeHardDisk(string pcType); 17 protected abstract void MakeDisplayCard(string pcType); 18 protected abstract void MakeKeyboard(string pcType); 19 protected abstract void MakeMainboard(string pcType); 20 21 private void MakeOver() 22 { 23 Console.WriteLine(pcType + "造好了!"); 24 } 25 26 //模板方法 27 public void MakePC() 28 { 29 MakeCPU(pcType); 30 MakeRAM(pcType); 31 MakeHardDisk(pcType); 32 MakeDisplayCard(pcType); 33 MakeKeyboard(pcType); 34 MakeMainboard(pcType); 35 36 MakeOver(); 37 } 38 }
2、具体模板角色,实现父类所定义的一个或多个抽象方法,具体类型电脑的实现。
1 // 具体摸板角色 2 // 实现父类所定义的一个或多个抽象方法。 3 // 每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现。 4 public class NotePc : PCTemplate 5 { 6 public NotePc(string pcType) : 7 base(pcType) 8 { 9 10 } 11 12 protected override void MakeCPU(string pcType) 13 { 14 Console.WriteLine(pcType + "的CPU造好了。。。"); 15 } 16 17 protected override void MakeRAM(string pcType) 18 { 19 Console.WriteLine(pcType + "的内存造好了。。。"); 20 } 21 22 protected override void MakeHardDisk(string pcType) 23 { 24 Console.WriteLine(pcType + "的硬盘造好了。。。"); 25 } 26 27 protected override void MakeDisplayCard(string pcType) 28 { 29 Console.WriteLine(pcType + "的显卡造好了。。。"); 30 } 31 32 protected override void MakeKeyboard(string pcType) 33 { 34 Console.WriteLine(pcType + "的键盘造好了。。。"); 35 } 36 37 protected override void MakeMainboard(string pcType) 38 { 39 Console.WriteLine(pcType + "的主板造好了。。。"); 40 } 41 }
3、客户端代码
1 public class Client 2 { 3 static void Main(string[] args) 4 { 5 PCTemplate notePC = new NotePc("笔记本电脑"); 6 notePC.MakePC(); 7 8 Console.Read(); 9 } 10 }
运行结果:
四、原型模式的实现要点
- Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
- 除了可以灵活应对子步骤的变化外,“不用调用我,让我来调用你”的反向控制结构是Template Method的典型应用。
- 在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法,纯虚方法),但一般推荐将它们设置为protected方法。
五、原型模式的适用性
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。这是Opdyke和Johnson所描述过的“重分解以一般化”的一个很好的例子。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
- 控制子类扩展。模板方法只在特定点调用“Hook”操作,这样就只允许在这些点进行扩展。