目錄
1.導讀
2.裝飾者模式介紹
3.代碼執行個體
3.1 以學習英雄的技能為例
3.2 以更換英雄的皮膚為例
1.導讀
大家好,首先我們來看兩個圖,下面兩個圖想必很多人都認識吧,不認識也沒關系,後面告訴你!
這是我最喜歡的射手-薇恩
這是打野的信仰-盲僧
好了,圖随便看下就可以了,你以為我真的要跟你們講英雄聯盟嗎,别逗了,我不敢!不廢話了,其實今天,我是打算以英雄聯盟為例,給大家分享一下關于“裝飾者模式”的知識。
玩過英雄聯盟的應該都知道,聯盟的每個英雄基本上都有皮膚,人氣高的英雄皮膚會特别多,每個個皮膚,都是英雄的一種妝扮,可以簡單地了解為是一套衣服。我們把這個英雄的皮膚和“裝飾者模式”聯系起來看的話,那麼一個英雄可以當成是被裝飾的對象,而不同的皮膚,就是進行不同裝飾後的樣子。
每個英雄都還有四個技能,玩家釋放技能的時候,一般都是按QWER,四個按鍵對應四個技能。每個技能其實也可以看成是英雄的一種裝飾,不過與皮膚不同的是,遊戲規定一個英雄在同一局遊戲裡面隻能使用一種皮膚,但是在一局遊戲裡面,英雄會同時擁有四個技能。
在文中,我将分别以技能和皮膚為例,編寫兩段代碼,來深入地了解一下“裝飾者模式”的運用。
2.裝飾者模式介紹
概念:裝飾器模式(Decorator Pattern)允許向一個現有的對象添加新的功能,同時又不改變其結構。這種類型的設計模式屬于結構型模式,它是作為現有的類的一個包裝。這種模式建立了一個裝飾類,用來包裝原有的類,并在保持類方法簽名完整性的前提下,提供了額外的功能。
何時使用:一般的,我們為了擴充一個類經常使用繼承方式實作,但是随着繼承層次的增加和擴充功能的增多,子類會很膨脹。如果希望在不增加很多子類的情況下擴充類的功能,那麼就可以使用裝飾者模式,動态地給一個對象添加一些額外的職責。
如何使用:将具體功能職責劃分,讓每個職能繼承裝飾者基類。
優點:裝飾類和被裝飾類可以獨立發展,不會互相耦合,裝飾模式是繼承的一個替代模式,裝飾模式可以動态擴充一個實作類的功能。
缺點:多層裝飾比較複雜,可能會增加代碼量
3.代碼執行個體
3.1 以學習英雄的技能為例
#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;
}
3.2 以更換英雄的皮膚為例
#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;
}