模板方法模式C++实现
1定义
定义一个操作的算法的框架,而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
实现方案:将算法/逻辑框架放在抽象基类中,并定义好实现接口,在子类中实现细节接口。
注:策略模式,解决的是相同的问题,只是其方案是将各个接口封装为类,通过委托/组合方式解决问题
2类图
3实现
class AbstractClass
{
public:
void Run()
{
DoA();
DoB();
DoC();
}
virtual void DoA()=0;
virtual void DoB()=0;
virtual void DoC()=0;
};
class ConcreteClass:public AbstractClass
{
public:
void DoA()
{
cout << “开车门”<<endl;
}
void DoB()
{
cout << “关车门”<<endl;
}
void DoC()
{
cout << “发车走人”<<endl;
}
};
void Test()
{
AbstractClass *car = new ConcreteClass();
car->Run();
}
3成员
基本方法,由子类实现的方法,并且在模板方法中被调用。
模板方法,是一个或者几个,一般是一个具体方法/框架,实现对基本方法的调度,完成固定的逻辑。
4应用
①优点
封装不变部分/逻辑框架,扩展可变部分/具体细节
提取公共部分代码,便于维护
行为由父类控制,子类实现–>基本方法子类实现,因此子类可以通过扩展的方式增加相应的功能,符合开闭原则
②缺点
因为模板方法将依赖点到,抽象中的框架实现依赖具体类的细节实现。所以是子类行为影响了父类。在复杂项目中,会造成代码阅读困难。
5 使用场景
多个子类有共有的方法,并且逻辑相同/逻辑相同,细节有差异
对重要,复杂的算法,可以讲核心算法设计为模板方法,周边细节由子类实现
重构时,经常使用的方案,将相同的代码抽象到父类,通过钩子函数约束行为。
6扩展
①对于原定框架中的模板方法,如果存在子类中对某个接口的具有选择性(执行或者不执行),那么在调用时就需要具体判别这种差异性调用。
②对这种选择性,用过钩子,策略模式等方案。判别,调用。然后在子类中实现具体的钩子定义。
7狡辩
父类调用子类的方法:
①把子类传递到父类的有残构造函数,然后调用
②使用反射的方式调用
③父类调用子类的静态方法
虽然这几种方式也实现了父类调用子类方法,但是在项目中并不能运用。子类简历框架,子类在重写了父类部分方法后,再调用从父类集成的方法,产生不同的结果。这正是模板方法–曲线救国。
8应用
在开元框架中,模板方法提供了一个抽象类,然后开元框架写一堆子类。如果需要扩展功能,可以继承这个抽象类,然后覆写protected方法,然后调用一个execute(run)方法,就完成功能扩展。