当前位置 博文首页 > Allen Roson:C++设计模式2——装饰者模式

    Allen Roson:C++设计模式2——装饰者模式

    作者:[db:作者] 时间:2021-06-22 21:13

    目录

    ?

    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;
    }
    
    

    下一篇:没有了