C++设计模式---模板方法模式
文章目录
- 模板方法模式的作用
- 具体的定义方式
- 具体的应用情景
模板方法模式的作用
在固定步骤确定的情况下,通过多态机制在多个子类中对每个步骤的细节进行差异化实现。
比如一个到餐馆吃饭的流程:点餐(粤菜,鲁菜)->吃饭->结账(现金,微信),不同的人在各个环节都有不同的动作,但流程是一样的,此时就可以采用多态实现这种差异化。
具体的定义方式
父类中定义了一个操作中的算法的骨架(稳定部分),而将一些步骤延迟到子类中去实现(比如父类中定义虚函数,子类中重写虚函数)。
通过这样的方式,达到在整体稳定的情况下,能够产生一些变化的目的。
模板方法模式也被认为导致了一种反向控制结构,这种结构也被称为好莱坞法则,也就是不用来调用我,我会去调用你的,即父类调用了子类的函数。
具体的应用情景
假设你现在是一名游戏程序员,游戏策划想让你实现一个战士类,这个类有生命、魔法、攻击力等属性,并且有一个“燃烧的技能”,能够让所有敌人掉血,但是自己也会掉血,你可以这样实现:
#include<iostream>
using namespace std;
class Warrior {
public:
Warrior(int life,int magic,int attack)
:m_life(life)
,m_magic(magic)
,m_attack(attack){}
//燃烧技能
void JN_Burn()
{
cout << "让所有敌人每人失去500生命,相关逻辑代码略过。。。" << endl;
cout << "主角自身失去300生命" << endl;
m_life -= 300;
cout << "播放燃烧技能的动画" << endl;
}
private:
//角色属性
int m_life;//生命
int m_magic;//魔法值
int m_attack;//攻击力
};
int main()
{
Warrior morleobj(1000, 0, 200);
morleobj.JN_Burn();//释放燃烧技能
}
现在游戏策划又想让你实现一个“法师”类,这个类和战士类的成员属性一样,唯一的不同是“燃烧”技能不会让自己掉血而是掉魔法值。并且策划告诉你,每个类都有一个“燃烧”技能。
你发现“法师”类和“战士”类大部分代码是相同的,那此时你直接实现一个“战斗者”的抽象类,让“战士”类和“法师”类继承“战斗者”类。
#include<iostream>
using namespace std;
//抽象类
class Fighter {
public:
Fighter(int life, int magic, int attack)
:m_life(life)
, m_magic(magic)
, m_attack(attack) {}
virtual ~Fighter() {}
//燃烧技能
void JN_Burn()
{
effect_enemy();//对敌人产生影响
effect_self();//对自身产生影响
play_effect();//播放“燃烧”技能特效,由于经费不足,这个技能特效所有类都相同
}
private:
virtual void effect_enemy() = 0;
virtual void effect_self() = 0;
void play_effect()
{
//实现“燃烧”特效
cout << "播放燃烧技能的特效,由于经费不足,这个技能特效所有类都相同,不需要虚函数" << endl;
}
protected://因为可能会被子类访问,所以不使用private
//角色属性
int m_life;//生命
int m_magic;//魔法值
int m_attack;//攻击力
};
//战士类
class F_Warrior:public Fighter {
public:
F_Warrior(int life, int magic, int attack)
:Fighter(life,magic,attack){}
private:
//实现父类的纯虚函数
virtual void effect_enemy()
{
cout << "战士让所有敌人每人失去500生命,相关逻辑代码略过。。。" << endl;
}
virtual void effect_self()
{
cout << "战士主角自身失去300生命" << endl;
m_life -= 300;
}
};
//法师类
class F_Mage :public Fighter {
public:
F_Mage(int life, int magic, int attack)
:Fighter(life, magic, attack) {}
private:
//实现父类的纯虚函数
virtual void effect_enemy()
{
cout << "法师让所有敌人每人失去650生命,相关逻辑代码略过。。。" << endl;
}
virtual void effect_self()
{
cout << "法师主角自身失去100魔法值" << endl;
m_magic -= 100;
}
};
int main()
{
Fighter* p1 = new F_Warrior(1000, 0, 200);
Fighter* p2 = new F_Mage(5000, 500, 300);
//战士和法师释放燃烧技能
p1->JN_Burn();
cout << "----------------" << endl;
p2->JN_Burn();
}
上面的代码已经引入了“模板方法模式”,不同的类通过父类指针调用同一个函数JN_Burn,由于多态机制,子类重写了JN_Burn中的虚函数。
JN_Burn这个函数中调用的函数数量和顺序总是固定的,因此这个函数就可以称为“模板”。
至此不同的子类产生了不同的效果,但所有子类的执行流程完全相同。