今天开始学习设计模式中的第三个类型——行为型模式。
行为模式:
行为型模式涉及到算法和对象间职责的分配。将注意力从控制流转移到对象间的联系方式上来。
行为模式分为:行为类模式和行为对象模式。行为类模式使用继承机制在类间分派行为;行为对象模式使用对象复合而不是继承。
Template Method
模板方法模式
Template Method
模板方法模式介绍:
Template Method
模板方法模式是一种行为型模式,具体点说是行为类型模式。主要解决在软件构建过程中,对于某一项任务,常常有稳定的整体操作结构,但各个子步骤却有很多改变的需求,或者由于固有的原因而无法和任务的整体结构同时实现。
GoF
《设计模式》中说道:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
Template Method
使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤
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(newBORA());
Console.Read();
}
}
public
class
ClientApp
{
public
static
void Drive(AbstractCar car)
{
car.DriveOnTheRoad();
}
}
运行结果如下:
BORA is StartUp
BORA is Running
BORA is Stoped
Template Method
要点
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
,因为需要重新定义的操作越多,客户程序就越长