序言
这集带来大家一起学下装饰模式。装饰模式 看名字就能 猜到是干啥 就是用来 搞装修进行装饰的 嘛!没毛病,其实装饰模式 确实是用来装饰对象的 而且是为了解耦的。我们知道 类是生成对象的模板,我们如果要做得单一职责的话,那么每增加一个不一样的属性,都要添加一个新的子类,这样就会有很多种类。或许这些属性可能还不是通用的。那么怎样来解决呢?或许我们可以将那些要添加的属性或者动作 封装成 装饰器,你要啥 我就装饰啥呗。下面请看下面的装饰器的标准类图。
装饰模式标准类图
装饰模式案例
小明习武闯天下
小明同学是我们的主人公,它是我们需要修饰的对象。起初他只是一名学生普通人一个。后面 习武->六脉神剑->打狗棒->降龙18掌,各种属性值持续上升, 然后走上人生巅峰。当然我们后面添加的这些 功能 得用 装饰模式呗。用继承不合理吧。
小明习武类型图
小明习武代码实现
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
using namespace std;
//人物角色接口 待装饰抽象基类
class Hero
{
public:
virtual void showStatus() = 0;
public:
int m_ATK;//攻击力
int m_DEF;//防御力
int m_Power;//内功
int m_Look;//颜值
string m_Name;
};
//学生 具体待装饰的类
class Student :public Hero
{
public:
Student(string name)
{
m_ATK = 0;
m_DEF = 0;
m_Power = 0;
m_Look = 10;//学生初始有颜值
m_Name = name;
}
virtual void showStatus()
{
cout << m_Name <<" 攻击力:" << m_ATK << " 防御力:" << m_DEF << " 内功:" << m_Power << " 颜值:" << m_Look << endl;
}
};
//抽象技能类(装饰类的基类) ,学习武功 还是一个人,装饰类 很重要一点,有指向待装饰对象的指针 ,这样就可以 在要装饰对象 上装饰东西 或者 做一些动作
class AbstractSkillDecorator:public Hero
{
public:
AbstractSkillDecorator(Hero* hero)
{
this->hero = hero;
}
protected:
Hero* hero;
};
//学习 六脉神剑,具体的装饰类 ,学习之后 攻击力和颜值 增加
class SexSwordDecorator :public AbstractSkillDecorator
{
public:
SexSwordDecorator(Hero* hero):AbstractSkillDecorator(hero)
{
}
virtual void showStatus()
{
addSkill();//增加技能
cout << m_Name << " 攻击力:" << m_ATK << " 防御力:" << m_DEF << " 内功:" << m_Power << " 颜值:" << m_Look << endl;
}
private:
//装饰类 增加动作,修饰待装饰对象hero
void addSkill()
{
this->m_ATK = hero->m_ATK + 100;
this->m_DEF = hero->m_DEF;
this->m_Power = hero->m_Power;
this->m_Look = hero->m_Look + 100;
this->m_Name = hero->m_Name;
delete hero;
}
};
//学习丐帮的打狗棒,学习后 防御力增加100,颜值下降200 o(╥﹏╥)o
class HitDogDecorator :public AbstractSkillDecorator
{
public:
HitDogDecorator(Hero* hero):AbstractSkillDecorator(hero)
{
}
virtual void showStatus()
{
addSkill();
cout << "一不小心成了:" << newId << endl;
cout << m_Name << " 攻击力:" << m_ATK << " 防御力:" << m_DEF << " 内功:" << m_Power << " 颜值:" << m_Look << endl;
}
private:
//装饰类 增加动作,修饰待装饰对象hero
void addSkill()
{
this->m_ATK = hero->m_ATK;
this->m_DEF = hero->m_DEF + 100;
this->m_Power = hero->m_Power;
this->m_Look = hero->m_Look - 200;
this->m_Name = hero->m_Name;
this->newId = "丐帮帮主";
delete hero;
}
private:
string newId;//装饰类增加状态,修饰hero对象
};
//学习降龙18掌,学习后 内力 暴增 + 200
class Dragon18Decorator :public AbstractSkillDecorator
{
public:
Dragon18Decorator(Hero* hero) :AbstractSkillDecorator(hero)
{
}
virtual void showStatus()
{
addSkill();
cout << m_Name << " 攻击力:" << m_ATK << " 防御力:" << m_DEF << " 内功:" << m_Power << " 颜值:" << m_Look << endl;
}
private:
//装饰类 增加动作,修饰待装饰对象hero
void addSkill()
{
this->m_ATK = hero->m_ATK;
this->m_DEF = hero->m_DEF;
this->m_Power = hero->m_Power + 200;
this->m_Look = hero->m_Look;
this->m_Name = hero->m_Name;
delete hero;
}
};
int main(int argc, char *argv[])
{
//小明刚开始是学生,但是它有个英雄梦,从此踏入武林
Hero* xiaoMing = new Student("小明");
cout << "小明还是学生时----------" << endl;
xiaoMing->showStatus();
//被装饰类装饰后,原对象是否要进行释放 视情况而定 。
//这里我们不再需要原对象,所有在装饰类中装饰完原对象,就将原对象释放。
//小明学武 -> 六脉神剑->打狗棒-> 降龙18掌
xiaoMing = new SexSwordDecorator(xiaoMing);
cout << "学习六脉神剑后----------" << endl;
xiaoMing->showStatus();
xiaoMing = new HitDogDecorator(xiaoMing);
cout << "学习打狗棒后------------" << endl;
xiaoMing->showStatus();
xiaoMing = new Dragon18Decorator(xiaoMing);
cout << "学习降龙18掌后------------" << endl;
xiaoMing->showStatus();
return EXIT_SUCCESS;
}