曾经第一次学习设计模式的时候,总觉得这玩意没有用。这段时间重新看视频学习,才领略到设计模式的好处。今天我想说说模板方法模式。
模板想必大家在生活中是经常用的。比如说写简历可以套一个简历模板,写一个网页可以套一个前端模板。当你使用一个模板的时候,你会根据自己的需求去修改模板的一部分内容。对于模板方法的使用和设计,与现实中的模板是基本一致的。这也是为什么它叫这个名字。
接下来我们考虑一个场景:用程序实现一个人一天的活动流程,包括吃早饭,吃午饭,打篮球,吃晚饭,跑步。这里限定吃饭的函数总是不变的
一开始你可能会写出如下代码,这是很自然的想法。
class Eat {
public:
void EatBreakFast() {}
void EatLunch() {}
void EatDinner() {}
};
class DoSport {
public:
void PlayBasketBall() {}
void Running() {}
};
int main()
{
Eat e;
DoSport ds;
e.EatBreakFast();
e.EatLunch();
ds.PlayBasketBall();
e.EatDinner();
ds.Running();
}
那么如果用模板方法模式来写呢?代码如下:
// DayInLife是一个模板
class DayInLife {
public:
void OneDay() {
EatBreakFast();
EatLunch();
PlayBasketBall();
EatDinner();
Running();
}
virtual void PlayBasketBall() = 0;
virtual void Running() = 0;
private:
void EatBreakFast() {
}
void EatLunch() {
}
void EatDinner() {
}
};
class MyDay : public DayInLife {
public:
// 实现两个virtual 函数
void PlayBasketBall() {
}
void Running() {
}
}
int main()
{
DayInLife* my = new MyDay();
my->OneDay();
return 0;
}
那么问题来了,使用模板方法到底有什么好处呢?
假设这个关于活动流程的类都是别人开发的,而你要使用这些类来实现你自己的功能。如果这些类是以第一种方式设计的,那么你每次写关于某个人一天的流程你都要把吃饭的动作给写上,比如说
// 第一个人的一天
Eat e;
DoSport ds;
e.EatBreakFast();
e.EatLunch();
ds.PlayBasketBall();
e.EatDinner();
ds.Running();
// 第二个人的一天, 因为每个人打篮球和跑步的方式不同所以你又设计了一个DoSport类
DoSport2 ds2;
e.EatBreakFast();
e.EatLunch();
ds2.PlayBasketBall();
e.EatDinner();
ds2.Running();
你知道对于每个人,他们的吃饭动作或者说函数都是一样的(场景设定的),你可能会自己封装一个函数
void OneDayInLife(DoSport* doSport) {
Eat e;
e.EatBreakFast();
e.EatLunch();
doSport->PlayBasketBall();
e.EatDinner();
doSport->Running();
}
但不管哪种方式,这些流程你都要来写一遍。然而这些流程是固定的,其中唯一有变化的地方只是人们运动的方式不一样,那么更好的想法是这些类的开发者把这些固定的动作封装起来,而把变化的部分暴露给使用者,让使用者根据自己的需求来自定义动作。这样子main中的代码也变得简洁了很多!
总的来说,如果这些类都是给自己使用的话,完全可以不用模板模式。然而考虑给别人用的话,那么使用者就会获得很大的便利。这就是设计模式的好处,方便类的使用者来开发程序!