定义:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
主要解决在软件构建过程中,对于某一项任务,常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因而无法和任务的整体结构同时实现。
定义一个场景:我想大家都玩过极品飞车(我相当喜欢)。游戏中有很多的汽车,但是从操作角度看大同小异。无非是起步(StartUp)、行驶(Run)、停车(Stop)等等行为。汽车行驶的动作之间可能存在着差异,例如:手动档和自动档,但是接口是一样的,换句话说,基本都是这几个动作。结合Template Method模式讲就是在这个程序中,结构(对汽车的操作)是稳定的,但是变化在于各个子步骤(操作行为的具体实现)。
程序实现与结构分析
首先我们需要一个汽车的抽象类(结构图中的AbstractClass)
public abstract class AbstractCar
{
protected abstract string StartUp();
protected abstract string Run();
protected abstract string Stop();
public void DriveOnTheRoad()
{
Console.WriteLine(StartUp());
Console.WriteLine(Run());
Console.WriteLine(Stop());
}
}
在这段代码中,抽象方法StartUp、Run、Stop叫做primitive operation(原语操作),它们是在子类中的扩展点,例如我们要编写一辆BORA的实现,在他继承AbstractCar后,可以在这几个primitive operation上进行自己个步骤的实现。
AbstractCar中的DriveOnTheRoad方法叫做template method(模板方法),template method用primitive operation定义一个算法,是相对稳定的部分。(子类中重新定义primitive operation)。
然后我们要实现一辆BORA汽车(结构图中的ConcreteClass)
public class BORA : AbstractCar //继承
{
protected override string StartUp()
{
return "BORA is StartUp";
}
protected override string Run()
{
return "BORA is Running";
}
protected override string Stop()
{
return "BORA is Stoped";
}
}
客户程序的实现
class Program
{
static void Main(string[] args)
{
ClientApp.Drive(new BORA());
Console.Read();
}
}
public class ClientApp
{
public static void Drive(AbstractCar car)
{
car.DriveOnTheRoad();
}
}
运行结果如下:
BORA is StartUp
BORA is Running
BORA is Stoped
要点:
1、 Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为了很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。
2、 除了可以灵活应对子步骤的变化外,“Don't call me.Let me Call you”的反向控制结构是Template Method的典型应用。“Don’t call me.Let me Call you”是指一个父类调用一个子类的操作,而不是相反。
3、 在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将它们设置为protected方法。可以没有具体实现的方法应该称为hook operation(钩子操作),提供了缺省的行为,子类可以在必要时进行扩展。
4、 尽量减少primitive operation,因为需要重新定义的操作越多,客户程序就越长