模板方法(template mathod)
在基类定义一个算法骨架,而将算法中的某些步骤推迟到子类中实现。也可以用钩子方法来选择算法骨架中的分支。
UML结构图
如上图所示:对于一些算法,我们可也将算法骨架个抽象出来,形成抽象的基类。但是对于算法中的某些步骤,我们暂时无法写出来,因为不同的使用者,对于这些步骤有不同的实现方式。因此在基类中我们用虚方法来定义这些步骤,子类继承基类,并在子类中重写override这些步骤。
应用场景
- 算法骨架与具体步骤之间的开发存在明显的先后顺序。
- 复杂的算法可以抽象成统一的骨架,对于其中可变的步骤交给子类来实现。
优缺点
优点:
- 算法中统一的部分,不用可以复用。
- 可变步骤的扩展性良好,通过增加子类就可以实现
- 如果算法骨架中有分支,可以通过钩子方法来实现
缺点:
- 如果可变步骤存在的情况过多,将会使得代码变得庞大,难以理解,此时可以结合桥接模式来设计。
例子
一个大公司来到学校进行招聘,对于一般学生招聘的流程是一样的,但是有后台的学生就可以不参加,而且每个人拿到的工资也不同。
代码:
#include<iostream>
using namespace std;
// 公司
class BigCompany
{
public:
virtual ~BigCompany() {}
// 校园招聘
void Recruit() {
std::cout << "---------- Begin ----------" << std::endl;
CareerTalk();
ReceiveResume();
if(is_or_not_Interview()) Interview();
Offer();
std::cout << "---------- End ----------" << std::endl;
}
// 宣讲会
void CareerTalk() {
std::cout << "宣讲会" << std::endl;
}
// 接收简历
void ReceiveResume() {
std::cout << "接收简历" << std::endl;
}
// 面试
void Interview(){
std::cout << "进行面试" << std::endl;
}
// 发放 Offer
virtual void Offer() = 0;
//是否进行面试,钩子方法
virtual bool is_or_not_Interview(){
return true;//默认需要进行面试
}
};
class G_Student : public BigCompany{//普通学生
public:
void Offer(){
std::cout << "拿到offer,每年15W" << std::endl;
}
};
class F_Student : public BigCompany{//老板小舅子
public:
bool is_or_not_Interview(){
return false;//当然不需要面试啦
}
void Offer(){
std::cout << "拿到offer,每年30W" << std::endl;
}
};
int main(){
G_Student student_1;
F_Student student_2;
student_1.Recruit();
student_2.Recruit();
return 0;
}
结果:
---------- Begin ----------
宣讲会
接收简历
进行面试
拿到offer,每年15W
---------- End ----------
---------- Begin ----------
宣讲会
接收简历
拿到offer,每年30W
---------- End ----------