仅作参考
前言
GOF-23 模式分类:
-》从目的来看:
•创建型(Creational)模式:将对象的部分创建工作延迟到子类或者其他对象,从而应对需求变化为对象创建时具体类型实现引来的冲击。
•结构型(Structural)模式:通过类继承或者对象组合获得更灵活的结构,从而应对需求变化为对象的结构带来的冲击。
从封装变化角度对模式分类:
此处只对模式特点进行分类,并不表明该模式不具备其他特点。
重构获得模式Refactoring to Patterns
重构关键技法
“组件协作”模式:
Template Method 模式:
动机(Motivation)
具体案例:
//程序库开发人员
class Library{
public:
void Step1(){
//...
}
void Step3(){
//...
}
void Step5(){
//...
}
};
在该类中,程序开发人员设定了固定的方法step1,step3,step4;
//应用程序开发人员
class Application{
public:
//由于应用需求增加的功能函数
bool Step2(){
//...
}
void Step4(){
//...
}
};
int main()
{
Library lib();
Application app();
lib.Step1();
if (app.Step2()){
lib.Step3();
}
for (int i = 0; i < 4; i++){
app.Step4();
}
lib.Step5();
}
可以看到,主函数在启用Application时进行调用的步骤,假设该应用调用过程相对一定,那么对于多个应用程序来说,重复的调用相同函数会导致极大的资源浪费,不如实现运行函数,变化部分由子类具体实现,更改代码如下:
//程序库开发人员
class Library{
public:
//稳定 template method,
void Run(){
Step1();
if (Step2()) { //支持变化 ==> 虚函数的多态调用
Step3();
}
for (int i = 0; i < 4; i++){
Step4(); //支持变化 ==> 虚函数的多态调用
}
Step5();
}
//虚析构函数原因:当子类进行删除时,调用对应的析构函数
virtual ~Library(){ }
protected:
/**之所以设置为proteced,是因为这些step函数只有在处于一个流程或过程中
才有意义**/
void Step1() { //稳定
//.....
}
void Step3() {//稳定
//.....
}
void Step5() { //稳定
//.....
}
virtual bool Step2() = 0;//变化
virtual void Step4() =0; //变化
};
可以看出,在修改后,具体的调用流程由library中的Run函数实现,而Run函数通过虚函数的多态调用实现不同应用的调用
//应用程序开发人员
class Application : public Library {
protected:
virtual bool Step2(){
//... 子类重写实现
}
virtual void Step4() {
//... 子类重写实现
}
};
int main()
{
Library* pLib=new Application();
lib->Run();
delete pLib;
}
}
早绑定与晚绑定
library先于application创建,在未改变前,程序主流程实现要依靠library中的函数,此称为早绑定
而在改变后,具体的内容依旧由application提供,但是具体的实现流程是固定的,依靠于application的具体函数实现.
模式定义:
结构:
要点总结:
1. Template Method模式是一种非常基础性的设计模式,在面向对象系统中有着大量的应用。它用最简洁的机制(虚函数的多态性)为很多应用程序框架提供了灵活的扩展点,是代码复用方面的基本实现结构。(扩展点指子类可以重定义操作具体的行为)
2.除了可以灵活应对子步骤的变化外,“不要调用我,让我来调用你”的反向控制结构是Template Method的典型应用。
3.在具体实现方面,被Template Method调用的虚方法可以具有实现,也可以没有任何实现(抽象方法、纯虚方法),但一般推荐将它们设置为protected方法。
模板方法的适用性
一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
各子类中公共的行为应被提取出来,并集中到一个公共父类中以避免代码重复。
控制子类扩展。(钩子操作(hook operations))