设计模式--装饰器模式

设计模式–装饰器模式

思路

根据父类设计装饰器类,并在使用的时候实现新的子类,每次使用装饰器得到的指针地址都会变化。

优点

1.灵活性:可以在运行时动态地给对象添加功能,而不需要修改对象的原始代码。
2.可维护性:装饰器模式遵循开闭原则,即对扩展开放,对修改关闭。如果要添加新的功能,只需要创建新的装饰器类并实现相应的功能即可,不需要修改已经存在的类的代码。
3.单一原则:每个装饰器类都专注于一个功能的添加,这使得代码的内聚性较高。

设计

首先有一个抽象英雄类,再有一个具体英雄类A、抽象装饰器类全都继承抽象英雄类,最后有一个具体装饰器类继承抽象装饰器类。
这种模式实际上就是用具体装饰器指针拷贝具体英雄类A的数据,并进行一些想要增加的操作,最后由于全都继承抽象英雄类,所以根据多态的使用,都能正常指向。

#include <iostream>

// 抽象的英雄
class AbstractHero
{
public:
    virtual void showStatus() = 0;

    int mHp;
    int mMp;
    int mAt;
    int mDf;
};

class HeroA : public AbstractHero
{
public:
    HeroA()
    {
        mHp = 0;
        mMp = 0;
        mAt = 0;
        mDf = 0;
    }

    virtual void showStatus()
    {
        std::cout << "血量:" << mHp << std::endl;
        std::cout << "魔法:" << mMp << std::endl;
        std::cout << "攻击:" << mAt << std::endl;
        std::cout << "防御:" << mDf << std::endl;
    }
};

// 抽象的装备装饰器
class AbstractEquipment : public AbstractHero
{
public:
    AbstractEquipment(AbstractHero* hero)
    {
        this->pHero = hero;
        std::cout << "抽象装饰器,被装饰对象地址:" << pHero << std::endl;
    }

    virtual void showStatus()
    {
    }

    AbstractHero* pHero;
};

// 增加防御的铠甲装饰器
class ArmorEquipment : public AbstractEquipment
{
public:
    ArmorEquipment(AbstractHero* hero) : AbstractEquipment(hero) {}

    void AddArmorEffect()
    {
        std::cout << "英雄穿上铠甲之后" << std::endl;
        this->mHp = this->pHero->mHp;
        this->mMp = this->pHero->mMp;
        this->mAt = this->pHero->mAt;
        this->mDf = this->pHero->mDf + 30;
    }

    virtual void showStatus()
    {
        AddArmorEffect();
        std::cout << "血量:" << mHp << std::endl;
        std::cout << "魔法:" << mMp << std::endl;
        std::cout << "攻击:" << mAt << std::endl;
        std::cout << "防御:" << mDf << std::endl;
        std::cout << "铠甲装饰器调用" << std::endl;
        pHero->showStatus();
    }
};

// 增加攻击的武器装饰器
class WeaponEquipment : public AbstractEquipment
{
public:
    WeaponEquipment(AbstractHero* hero) : AbstractEquipment(hero) {}

    void AddWeaponEffect()
    {
        std::cout << "英雄装备武器之后" << std::endl;
        this->mHp = this->pHero->mHp;
        this->mMp = this->pHero->mMp;
        this->mAt = this->pHero->mAt + 50;
        this->mDf = this->pHero->mDf;
    }

    virtual void showStatus()
    {
        AddWeaponEffect();
        std::cout << "血量:" << mHp << std::endl;
        std::cout << "魔法:" << mMp << std::endl;
        std::cout << "攻击:" << mAt << std::endl;
        std::cout << "防御:" << mDf << std::endl;
        std::cout << "武器装饰器调用" << std::endl;
        pHero->showStatus();
    }
};

void test01()
{
    AbstractHero* hero = new HeroA;
    hero->showStatus();
    std::cout << "-------------------" << std::endl;

    // 给英雄穿上铠甲
    hero = new ArmorEquipment(hero);
    hero->showStatus();
    std::cout << "-------------------" << std::endl;

    // 给英雄装备武器
    hero = new WeaponEquipment(hero);
    hero->showStatus();
    std::cout << "-------------------" << std::endl;

    hero->showStatus();
}

int main()
{
    test01();
    return 0;
}

血量:0
魔法:0
攻击:0
防御:0
抽象装饰器,被装饰对象地址:0x620e70
英雄穿上铠甲之后
血量:0
魔法:0
攻击:0
防御:30
铠甲装饰器调用
血量:0
魔法:0
攻击:0
防御:0
抽象装饰器,被装饰对象地址:0x621ea0
英雄装备武器之后
血量:0
魔法:0
攻击:50
防御:30
武器装饰器调用
英雄穿上铠甲之后
血量:0
魔法:0
攻击:0
防御:30
铠甲装饰器调用
血量:0
魔法:0
攻击:0
防御:0
英雄装备武器之后
血量:0
魔法:0
攻击:50
防御:30
武器装饰器调用
英雄穿上铠甲之后
血量:0
魔法:0
攻击:0
防御:30
铠甲装饰器调用
血量:0
魔法:0
攻击:0
防御:0

具体怎么理解呢,就是一开始有一个具体英雄A对象,但是我想增加一个新的方法,但是如果直接改动A对象不是很好
,而且以后如果还想增加新的方法,那岂不是会经常继承然后重写showStatus呢。
所以我就使用一个同样继承抽象英雄类的抽象装饰器类,后续如果想增加就继承这个抽象装饰器类就行。
得到具体装饰器类后就可以写新的方法了,放在虚函数showStatus里面就行。由于创建具体装饰器指针的时候里面也会创建个AbstractHero指针,所以如果传入一个具体英雄对象(或者其他装饰器指针)也能接受数据,所以新增加的方法都是对这个类里面的新指针进行操作。
每次使用装饰器都会产生新的指针。按照案例给的代码,这里就会有三个指针,分别指向HeroA、ArmorEquipment、WeaponEquipment。如果想获得第三个指针的数据,那么第一个、第二个指针都不能删除,因为数据都是根据这些指针算出来的,并且在指针内部都有一个指针指向前面的指针的。
感觉跟混入的概念有点像。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值