应用背景
在软件构建中,对于某一项任务,常常有着稳定的整体操作结构,但是各个子步骤之间却有很多改变的需求,或者由于固有的原因(比如框架与应用之间的关系)而不发和任务的整体结构同时实现
那么如何在确定稳定操作结构的前提下,来灵活应对各个子步骤或者晚期实现需求。
模式定义
定义一个操作中的算法的骨架(稳定),而讲一些步骤延迟变化到子类中,模板模式可以使子类不改变(复用)一个算法的结构即可重定义该算法的某些特定步骤
代码
没有使用模板模式的代码如下
class Template
{
public:
void StepOne()
{
printf("这是步骤一\n");
}
virtual void StepTwo() = 0;
void StepThree()
{
printf("这是步骤三\n");
}
virtual void StepFour() = 0;
void StepFive()
{
printf("这是步骤五\n");
}
};
class ConcreteProject:public Template
{
virtual void StepTwo()
{
printf("这是步骤二\n");
}
virtual void StepFour()
{
printf("这是步骤四\n");
}
public:
void Run()
{
StepOne();
StepTwo();
StepThree();
StepFour();
StepFive();
}
};
int main()
{
ConcreteProject project;
project.Run();
}
得到的结果为
但是这样子的代码会有什么问题呢?
一般而言模板模式都是用在框架之间,具体的步骤已经确定下来了,只需要写一下某些步骤的程序就好,但是这个程序里面还写了Run函数,也就是说业务开发者还需要自己写代码决定顺序。
class Template
{
public:
void StepOne()
{
printf("这是步骤一\n");
}
virtual void StepTwo() = 0;
void StepThree()
{
printf("这是步骤三\n");
}
virtual void StepFour() = 0;
void StepFive()
{
printf("这是步骤五\n");
}
void Run()
{
StepOne();
StepTwo();
StepThree();
StepFour();
StepFive();
}
};
class ConcreteProject:public Template
{
virtual void StepTwo()
{
printf("这是步骤二\n");
}
virtual void StepFour()
{
printf("这是步骤四\n");
}
public:
};
int main()
{
ConcreteProject project;
project.Run();
}
把Run函数写入到Template中,这样子业务员就不需要写运行函数。
总结
模板模式是一种基础性的设计模式,在面向对象系统中有着大量的应用,它用最简单的机制为很多应用程序提供了灵活的扩展点
除了可以灵活应对子步骤的变化外,”不要调用我,用我来调用你“的反向控制结构是模板模式的典型应用
在具体实现上,被模板模式调用的虚方法可以是具体实现,也可以是没有任何实现,但是一般将其设为protected方法