模板方法(Template Method)模式
用途
模板方法:在步骤确定且固定的情况下,通过多态机制在多个子类中对每个步骤的细节进行差异化实现,这是模板方法能够达到的效果;
分类
模板方法模式:在设计模式中属于行为型模式;
具体例子
A公司有一个小游戏项目组——开发单机闯关打斗类游戏(类似街机打拳类游戏)。
一个游戏项目组最少需要三名担任不同角色的员工组成:游戏策划,游戏程序,游戏美术
-
游戏策划:简称策划 ,负责提出游戏的各种玩法需求,确定游戏中各种数值比如人物(敌人)的生命值、魔法值。
-
游戏程序:简称程序,需要与游戏策划紧密配合通过代码来实现游戏策划要求的各种游戏功能。
-
游戏美术:角色设计,道具设计,游戏特效等等。
游戏策划需求:
游戏主角是个战士(攻击力不够强,生命值比较多,抗揍),主角通过不断的往前走来闯关,遇到敌人就进行攻击,敌人也会反击,敌人也会距离近时主动攻击主角。
角色分类:
-
战士
- 属性
- 生命值——1000
- 魔法值——0
- 攻击力——200
- 技能
- “燃烧”——使用该技能可以使附近所有敌人每人失去500点生命值,但是主角自身也会损失掉300点生命值。
- 属性
-
法师 (攻击力很强,生命值比较少,不抗揍)
- 属性
- 生命值:800
- 魔法值:200
- 攻击力:300
- 技能
- “燃烧”——使用该技能可以使附近所有敌人每人失去650点生命值,但是主角自身会损失掉100点魔法值。
战士和法师释放燃烧技能表现是不同的,这种不同的表现主要是通过Fighter和Magic子类中的effect_enemy和effect_self虚函数来体现;
- 属性
代码
#include <iostream>
namespace template_method {
class Warror {
public:
Warror(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack) {}
virtual ~Warror(){}
public:
void skill_burn() {
effect_enemy();
effect_myself();
play_effect();
}
private:
virtual void effect_enemy() {};
virtual void effect_myself() {};
void play_effect() {
std::cout << "释放技能特效" << std::endl;
}
protected:
int m_life;
int m_magic;
int m_attack;
};
class Fighter : public Warror {
public:
Fighter(int life, int magic, int attack) : Warror(life, magic, attack) {}
private:
virtual void effect_enemy() {
std::cout << "使敌人失去500点生命值" << std::endl;
}
virtual void effect_self() {
std::cout << "使自己失去300点生命值" << std::endl;
m_life -= 300;
}
};
class Magic : public Warror {
public:
Magic(int life, int magic, int attack) : Warror(life, magic, attack) {}
private:
virtual void effect_enemy() {
std::cout << "使敌人失去600点生命值" << std::endl;
}
virtual void effect_self() {
std::cout << "使自己失去200点魔法值" << std::endl;
m_magic -= 200;
}
};
};// end of namespace template_method
int main() {
template_method::Warror* proler_fighter = new template_method::Fighter(1000, 0, 200);
proler_fighter->skill_burn();
template_method::Warror* proler_magic = new template_method::Magic(800, 200, 300);
proler_magic->skill_burn();
delete proler_fighter;
delete proler_magic;
return 0;
}
总结
软件开发中需求变化频繁的,开发人员要尝试寻找变化点,把变化部分和稳定部分分离开来,在变化的地方应用设计模式。
CPP中两种绑定模式:
-
晚绑定:代码执行时才知道具体要执行哪个虚函数。
-
早绑定:编译时就能确定执行的是哪个子类(Fighter和Magic的effect_enemy或者effect_self)。
模板方法模式的定义(实现意图):定义了一个操作中的算法的骨架(稳定部分),而将一些步骤延迟到子类中去实现(父类中定义虚函数,子类中实现/重写这个虚函数),从而达到在整体稳定的情况下能够产生一些变化的目的。
设计模式的经典总结
-
设计模式的作用就是在变化和稳定中间寻找隔离点,分离稳定和变化,从而来管理变化。
-
模板方法模式也被认为导致了一种反向控制结构。这种结构被称为好莱坞法则(不要来调用我,我会去调用你)。
程序代码的进一步完善及应用联想
-
钩子方法:子类勾住父类从而反向控制父类行为的意思,因此起名为钩子方法。
-
MFC框架(微软基础类库):通过MFC创建一个基于对话框的应用程序。自动调用OnInitDialog成员函数(相当于effect_enemy或者effect_self这样的虚函数)。
参考资料:
1.王健伟:《C++设计模式》
2.程杰:《大话设计模式》
3.代码地址