当前位置 博文首页 > Allen Roson:C++设计模式2——装饰者模式
目录
?
1.导读
2.装饰者模式介绍
3.代码实例
3.1 以学习英雄的技能为例
3.2 以更换英雄的皮肤为例
?
?
大家好,首先我们来看两个图,下面两个图想必很多人都认识吧,不认识也没关系,后面告诉你!
这是我最喜欢的射手-薇恩
?
这是打野的信仰-盲僧
?
好了,图随便看下就可以了,你以为我真的要跟你们讲英雄联盟吗,别逗了,我不敢!不废话了,其实今天,我是打算以英雄联盟为例,给大家分享一下关于“装饰者模式”的知识。
玩过英雄联盟的应该都知道,联盟的每个英雄基本上都有皮肤,人气高的英雄皮肤会特别多,每个个皮肤,都是英雄的一种妆扮,可以简单地理解为是一套衣服。我们把这个英雄的皮肤和“装饰者模式”联系起来看的话,那么一个英雄可以当成是被装饰的对象,而不同的皮肤,就是进行不同装饰后的样子。
每个英雄都还有四个技能,玩家释放技能的时候,一般都是按QWER,四个按键对应四个技能。每个技能其实也可以看成是英雄的一种装饰,不过与皮肤不同的是,游戏规定一个英雄在同一局游戏里面只能使用一种皮肤,但是在一局游戏里面,英雄会同时拥有四个技能。
在文中,我将分别以技能和皮肤为例,编写两段代码,来深入地理解一下“装饰者模式”的运用。
?
概念:装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。
何时使用:一般的,我们为了扩展一个类经常使用继承方式实现,但是随着继承层次的增加和扩展功能的增多,子类会很膨胀。如果希望在不增加很多子类的情况下扩展类的功能,那么就可以使用装饰者模式,动态地给一个对象添加一些额外的职责。
如何使用:将具体功能职责划分,让每个职能继承装饰者基类。
优点:装饰类和被装饰类可以独立发展,不会相互耦合,装饰模式是继承的一个替代模式,装饰模式可以动态扩展一个实现类的功能。
缺点:多层装饰比较复杂,可能会增加代码量
?
?
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
//英雄接口
class Hero
{
public:
//换皮肤
virtual void ChangeSkin() = 0;
};
//ConcreteComponent 具体英雄盲僧
class Mangseng : public Hero
{
protected:
string name;
public:
Mangseng(string name)
{
this->name = name;
}
void ChangeSkin()
{
cout << name;
}
};
//装饰者基类——皮肤类
class Skin : public Hero {
//持有一个英雄对象接口
protected:
Hero *m_pHero;
public:
Skin(Hero *pHero)
{
this->m_pHero = pHero;
}
void ChangeSkin()
{
if (m_pHero != NULL)
m_pHero->ChangeSkin();
}
};
//盲僧皮肤之"龙的传人"
class Skin_LegendOfDragon : public Skin
{
private:
string m_strSkinName;
public:
Skin_LegendOfDragon(Hero *pHero, string strSkinName) :Skin(pHero)
{
this->m_strSkinName = strSkinName;
}
void ChangeSkin()
{
m_pHero->ChangeSkin();
cout << "换上了新皮肤:" << m_strSkinName << endl;
}
};
//盲僧皮肤之"泳池派对"
class Skin_PoolParty : public Skin
{
private:
string m_strSkinName;
public:
Skin_PoolParty(Hero *pHero, string strSkinName) :Skin(pHero)
{
this->m_strSkinName = strSkinName;
}
void ChangeSkin()
{
m_pHero->ChangeSkin();
cout << "换上了新皮肤:" << m_strSkinName << endl;
}
};
//盲僧皮肤之"SKT T1冠军皮肤"
class Skin_SKT : public Skin
{
private:
string m_strSkinName;
public:
Skin_SKT(Hero *pHero, string strSkinName) :Skin(pHero)
{
this->m_strSkinName = strSkinName;
}
void ChangeSkin()
{
m_pHero->ChangeSkin();
cout << "换上了新皮肤:" << m_strSkinName << endl;
}
};
int main()
{
Mangseng objMs("盲僧");
Skin_SKT skt(&objMs, "SKT T1冠军皮肤");
Skin_PoolParty poolParty(&objMs, "泳池派对");
Skin_LegendOfDragon dragon(&objMs, "龙的传人");
skt.ChangeSkin();
poolParty.ChangeSkin();
dragon.ChangeSkin();
return 0;
}
?
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
//英雄接口
class Hero {
public:
//学习技能
virtual void LearnSkill() = 0;
};
//具体英雄盲僧
class Mangseng : public Hero
{
protected:
string name;
public:
Mangseng(string name)
{
this->name = name;
}
void LearnSkill()
{
cout << name <<"学习了上述技能";
}
};
//装饰者基类——技能类
class SKill : public Hero
{
protected:
Hero *m_pHero;//持有一个英雄对象
public:
SKill(Hero *pHero)
{
this->m_pHero = pHero;
}
void LearnSkill()
{
if (m_pHero != NULL)
m_pHero->LearnSkill();
}
};
//盲僧Q技能"天音波/回音击"
class SKill_Q : public SKill
{
private:
string m_strSkillName;
public:
SKill_Q(Hero *pHero, string strSkinName) :SKill(pHero)
{
this->m_strSkillName = strSkinName;
}
void LearnSkill()
{
cout << "学习了Q技能:" << m_strSkillName << endl;
m_pHero->LearnSkill();
}
};
//盲僧W技能"金钟罩/铁布衫"
class SKill_W : public SKill
{
private:
string m_strSkillName;
public:
SKill_W(Hero *pHero, string strSkinName) :SKill(pHero)
{
this->m_strSkillName = strSkinName;
}
void LearnSkill()
{
cout << "学习了W技能:" << m_strSkillName << endl;
m_pHero->LearnSkill();
}
};
//盲僧E技能"天雷破/摧筋断骨"
class SKill_E : public SKill
{
private:
string m_strSkillName;
public:
SKill_E(Hero *pHero, string strSkinName) :SKill(pHero)
{
this->m_strSkillName = strSkinName;
}
void LearnSkill()
{
cout << "学习了E技能:" << m_strSkillName << endl;
m_pHero->LearnSkill();
}
};
//盲僧R技能"猛龙摆尾"
class SKill_R : public SKill
{
private:
string m_strSkillName;
public:
SKill_R(Hero *pHero, string strSkinName) :SKill(pHero)
{
this->m_strSkillName = strSkinName;
}
void LearnSkill()
{
cout << "学习了R技能:" << m_strSkillName << endl;
m_pHero->LearnSkill();
}
};
int main()
{
Mangseng objMs("盲僧");
SKill_R r(&objMs, "猛龙摆尾");
SKill_E e(&r, "天雷破/摧筋断骨");
SKill_W w(&e, "金钟罩/铁布衫");
SKill_Q q(&w, "天音波/回音击");
q.LearnSkill();
return 0;
}