1、定义
定义一个操作中的算法的骨架 ,而将一些步骤延迟到子类中。 Template Method使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。 ——《 设计模式》 GoF
- 算法的骨架:固定的流程
- 延迟到子类中:使子类也具有对应的流程,也就是继承下来
- 重定义该算法的某些特定步骤:重写虚函数
2、代码实现
代码背景:某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代更新表演流程
#include <iostream>
using namespace std;
class ZooShow {
public:
// 固定流程封装到这里
void Show() {
Show0();
Show1();
Show2();
Show3();
}
protected:
// 子流程 使用protected保护起来 不被客户调用 但允许子类扩展
virtual void Show0(){
cout << "ZooShow:show0" << endl;
}
virtual void Show2(){
cout << "ZooShow:show2" << endl;
}
virtual void Show1() {
cout << "ZooShow:show1" << endl;
}
virtual void Show3() {
cout << "ZooShow:show3" << endl;
}
};
class ZooShowEx : public ZooShow {
protected:
//重写了Show1、Show3,当再调用父类的Show函数时,里面的Show1、Show3就会换成子类的重写的函数
virtual void Show1(){
cout << "ZooShowEx : show1" << endl;
}
virtual void Show3(){
cout << "ZooShowEx : show3" << endl;
};
class ZooShowEx1 : public ZooShow {
protected:
virtual void Show0(){
cout << "ZooShowEx1 : show0" << endl;
}
virtual void Show2(){
cout << "ZooShowEx1 : show2" << endl;
}
};
class ZooShowEx2 : public ZooShow {
protected:
virtual void Show1(){
cout << "ZooShowEx2 : show1" << endl;
}
virtual void Show2(){
cout << "ZooShowEx2 : show2" << endl;
}
};
int main () {
ZooShow *zs = new ZooShowEx;
zs->Show(); //执行时会用ZooShowEx重写的函数替换父类中对应的虚函数
ZooShow* zs1 = new ZooShowEx1;
zs1->Show(); //执行时会用ZooShowEx重写的函数替换父类中对应的虚函数
return 0;
}
代码分析:
- 父类供一个公共的函数,里面封装好固定的流程
- 将每个流程函数设置为虚函数,让子类重写(便于后续扩展)
- 子类继承父类,并重写想要扩展的虚函数
- 创建子类对象,用父类指针接收
- 父类指针调用固定流程函数(多态)
3、要点
-
该设计模式是最常用的设计模式,子类可以复写父类子流程,使父类的骨架流程丰富
-
反向控制流程的典型应用(流程是规定好的,中间的步骤可以进行通过重写进行创新)
-
父类 使用protected 权限保护子类需要复写的子流程;这样子类的子流程只能父类来调用
- protected:防外,不防子类(子类可继承)
- private:除了友元,谁都防
-
流程是固定的,但是中间的几个步骤是可以创新的,第一想到的就是模板方法:父类定义骨架流程(由父类控制 流程函数的调用),子类重写进行创新,不让外界访问流程函数,防止其更改骨架流程,使用protected权限
4、本质
- 通过固定算法骨架来约束子类的行为(子类只能通过重写来创新某些步骤,但是不会改变固定的流程)