定义
模板方法(Template Method)是一种行为型设计模式,它定义了一个算法的骨架,将一些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
在模板方法模式中,定义一个操作中的算法骨架,而将一些步骤延迟到子类中实现。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。模板模式就像一个模板,我们只需要根据自己的需要填充相应的内容就可以了。
解决问题
稳定点:算法骨架
变化点:子流程需要变化
例如,我们可以定义一个抽象的爬山活动模板,模板中包含了准备活动、进行活动、结束活动等步骤,然后让具体的爬山活动子类去实现准备装备、选择路线等具体步骤。这样可以保证整个爬山活动的框架结构不变,但是每个具体的爬山活动可以根据实际情况进行个性化的定制。
代码结构
模板方法模式中包含两类角色:
1.抽象模板(Abstract Template)角色:定义抽象方法和具体方法,具体方法可以调用抽象方法,定义算法的骨架。
2.具体模板(Concrete Template)角色:实现抽象模板中的抽象方法,完成算法中的某些步骤。
设计原则
单一职责
开闭
依赖倒置:子类扩展时,依赖基类的虚函数实现;使用者只依赖接口
封装变化点:protected
接口隔离
最小知道
如何扩展
实现子类继承基类,复写子流程
通过多态调用方式使用
案例
某个品牌动物园,有一套固定的表演流程,但是其中有若干个表演子流程可创新替换,以尝试迭代更新表演流程。
一般实现方法:
#include <iostream>
using namespace std;
class ZooShow {
public:
ZooShow(int type = 1) : _type(type) {}
public:
void Show()
{
if (Show0())
{
PlayGame();
}
Show1();
Show2();
Show3();
}
private:
void PlayGame() {
cout << "after Show0, then play game" << endl;
}
bool Show0()
{
if (_type == 1)
{
return true;
} else if (_type == 2 )
{
}
cout << _type << " show0" << endl;
return true;
}
void Show1()
{
if (_type == 1)
{
cout << _type << " Show1" << endl;
} else if (_type == 2)
{
cout << _type << " Show1" << endl;
} else if (_type == 3)
{
}
}
void Show2() {
if (_type == 1)
{
cout << "base Show2" << endl;
}
else if (_type == 2)
{
cout << _type << " Show1" << endl;
}
}
void Show3()
{
if (_type == 1)
{
cout << _type << " Show1" << endl;
} else if (_type == 2)
{
cout << _type << " Show1" << endl;
}
}
private:
int _type;
};
int main () {
ZooShow *zs = new ZooShow(1);
zs->Show();
return 0;
}
但是如果想要修改某个若个或多个表演子流程,就需要在对应的子流程中增加if语句,或者修改某些if语句里的代码,整体很不稳定。
基于模板方法,改进后:
#include <iostream>
using namespace std;
class ZooShow {
public:
void Show()
{
if (Show0())
{
PlayGame();
}
Show1();
Show2();
Show3();
}
private:
void PlayGame()
{
cout << "after Show0, then play game" << endl;
}
bool expired;
protected:
virtual bool Show0()
{
cout << "show0" << endl;
if (! expired)
{
return true;
}
return false;
}
virtual void Show1() { cout << "show1" << endl;}
virtual void Show2() { cout << "show2" << endl; }
virtual void Show3() { cout << "show3" << endl;}
};
class ZooShowEx0: public ZooShow {
protected:
virtual void Show0()
{
if (! expired)
{
return true;
}
return false;
}
}
class ZooShowEx1 : public ZooShow
{
protected:
virtual bool Show0()
{
cout << "ZooShowEx1 show0" << endl;
if (! expired)
{
return true;
}
return false;
}
virtual void Show2()
{
cout << "show3" << endl;
}
};
class ZooShowEx2 : public ZooShow {
protected:
virtual void Show1()
{
cout << "show1" << endl;
}
virtual void Show2()
{
cout << "show3" << endl;
}
};
class ZooShowEx3 : public ZooShow {
protected:
virtual void Show1()
{
cout << "show1" << endl;
}
virtual void Show3()
{
cout << "show3" << endl;
}
virtual void Show4()
{
}
};
int main ()
{
ZooShow *zs = new ZooShowEx0;
zs->Show();
return 0;
}