c++装饰模式

本文通过运用设计模式比没用设计模式的优势在哪?
设计模式主要是要抓住稳定部分和易变部分,文章结尾会指出。

继承方式新增代码

#include <iostream>
using namespace std;

//吃鸡游戏有好多种枪,下面枪是原有代码,前人写好了。
//枪的抽象类
class Gun {
public:
    virtual void shoot() = 0;
    virtual ~Gun() {}
};

class M16 : public Gun {
public:
    void shoot() override {
        cout << "M16 射击" << endl;
    }
};

class AK : public Gun {
public:
    void shoot() override {
        cout << "AK 射击" << endl;
    }
};

class AWM : public Gun {
public:
    void shoot() override {
        cout << "AWM 射击" << endl;
    }
};

//现在的为枪增加消音器。
//改变源代码即会使原有的代码不稳定,也会使得Gun类变得越来越复杂,职责不单一,且和消音器耦合在一起。
//所以我们选择继承。下面也又修改代码的案例。
class SilencerM16 : public M16 {
public:
    void shoot() override {
        silence();
        M16::shoot();
    }
private:
    void silence() {
        cout << "使得枪声变小" << endl;
    }
};

class SilencerAK : public AK {
public:
    void shoot() override {
        silence();
        AK::shoot();
    }
private:
    void silence() {
        cout << "使得枪声变小" << endl;
    }
};

class SilencerAWM : public AWM {
public:
    void shoot() override {
        silence();
        AWM::shoot();
    }
private:
    void silence() {
        cout << "使得枪声变小" << endl;
    }
};

//需求有又要为枪支增加瞄准镜,且可以和消音器一起配代。
class ScopeSilencerAWM : public SilencerAWM {
public:
    void shoot() override {
        useScope();
        SilencerAWM::shoot();
    }

private:
    void useScope() {
        cout << "使用了瞄准镜" << endl;
    }
};

//...我的天,太多了。
//如果需求又要增加弹夹和枪托又该如何。

int main()
{
    Gun *ak = new AK;
    ak->shoot();
    
    Gun *silencer_ak = new SilencerAK;
    silencer_ak->shoot();
    
    Gun *scope_silencer_awm = new ScopeSilencerAWM;
    scope_silencer_awm->shoot();
    
    delete(ak);
    delete(silencer_ak);
    delete(scope_silencer_awm);

    return 0;
}

直接修改源代码

#include <iostream>
using namespace std;

//增加消音器
class Silencer {
public:
    void silence() {
        cout << "使得枪声变小了" << endl;
    }
};

//第二次需要增加瞄准镜
class Scope {
public:
    void scope() {
        cout << "瞄准镜" << endl;
    }
};

class Gun {
public:
    Gun() : silencer(nullptr), scope(nullptr) {}    //第一次修改新增代码,第二次修改改变代码
    Gun(Silencer *silencer, Scope *scope) : silencer(silencer), scope(scope) {} //第一次修改新增代码,第二次修改新增代码

    virtual void shoot() = 0;

    void setSilencer(Silencer *silencer) {  //第一次修改新增代码
        this->silencer = silencer;
    }

    void setScope(Scope *scope) {   //第二次修改新增代码
        this->scope = scope;
    }

protected:
    Silencer *silencer; //第一次修改新增代码
    Scope *scope;   //第二次修改新增代码
};

class M16 : public Gun {
public:
    M16() : Gun(nullptr, nullptr) {}    //第一次修改增加代码
    explicit M16(Silencer *silencer) : Gun(silencer, nullptr) {}   //第一次修改新增代码,第二次修改改变代码
    explicit M16(Scope *scope) : Gun(nullptr, scope) {}   //第二次修改新增代码
    M16(Silencer *silencer, Scope *scope) : Gun(silencer, scope) {}   //第二次修改新增代码
    void shoot() override {
        if (silencer) silencer->silence();    //第一次修改新增代码
        if (scope) scope->scope();  //第二次修改新增代码
        cout << "M16 射击" << endl;
    }
};

class AK : public Gun {
public:
    AK() : Gun(nullptr, nullptr) {}    //第一次修改增加代码
    explicit AK(Silencer *silencer) : Gun(silencer, nullptr) {}   //第一次修改新增代码,第二次修改改变代码
    explicit AK(Scope *scope) : Gun(nullptr, scope) {}   //第二次修改新增代码
    AK(Silencer *silencer, Scope *scope) : Gun(silencer, scope) {}   //第二次修改新增代码
    void shoot() override {
        if (silencer) silencer->silence();    //第一次修改新增代码
        if (scope) scope->scope();  //第二次修改新增代码
        cout << "AK 射击" << endl;
    }
};

class AWM : public Gun {
public:
    AWM() : Gun(nullptr, nullptr) {}    //第一次修改增加代码
    explicit AWM(Silencer *silencer) : Gun(silencer, nullptr) {}   //第一次修改新增代码,第二次修改改变代码
    explicit AWM(Scope *scope) : Gun(nullptr, scope) {}   //第二次修改新增代码
    AWM(Silencer *silencer, Scope *scope) : Gun(silencer, scope) {}   //第二次修改新增代码
    void shoot() override {
        if (silencer) silencer->silence();    //第一次修改新增代码
        if (scope) scope->scope();  //第二次修改新增代码
        cout << "AWM 射击" << endl;
    }
};
//所有枪的shoot方法可以用模板方法优化以下。
//如果需求又要增加弹夹和枪托又该如何。

int main()
{
    auto *silencer = new Silencer;
    auto *ak = new AK(silencer);
    ak->shoot();

    auto *scope = new Scope;
    ak->setScope(scope);
    ak->shoot();

    //注意释放顺序,不要出现指针悬挂。
    delete(ak);
    delete(scope);
    delete(silencer);

    return 0;
}

用继承组合模式修改代码(修饰模式)

#include <iostream>
using namespace std;

class Gun {
public:
    virtual void shoot() = 0;
};

class M16 : public Gun {
public:
    void shoot() override {
        cout << "M16 射击" << endl;
    }
};

class AK : public Gun {
public:
    void shoot() override {
        cout << "AK 射击" << endl;
    }
};

class AWM : public Gun {
public:
    void shoot() override {
        cout << "AWM 射击" << endl;
    }
};

//新增代码
//带装备的枪抽象类
class DecorateGun : public Gun {
public:
    DecorateGun(Gun *gun) : gun(gun) {}

protected:
    Gun *gun;
};

//新增消音器
class SilencerGun : public DecorateGun {
public:
    SilencerGun(Gun *gun) : DecorateGun(gun) {}
    void shoot() override {
        silence();
        gun->shoot();
    }

private:
    void silence() {
        cout << "枪的声音变小了" << endl;
    }
};

//新增瞄准镜
class ScopeGun : public DecorateGun {
public:
    ScopeGun(Gun *gun) : DecorateGun(gun) {}
    void shoot() override {
        scope();
        gun->shoot();
    }

private:
    void scope() {
        cout << "装上了瞄准镜" << endl;
    }
};

//新增xxx,无需修改源代码,直接新增一个类即可。

int main()
{
    auto *ak = new AK;
    ak->shoot();

    auto *silencer_ak = new SilencerGun(ak);
    silencer_ak->shoot();

    auto *scope_ak = new ScopeGun(silencer_ak);
    scope_ak->shoot();

    //注意释放顺序,不要出现指针悬挂。
    delete(scope_ak);
    delete(silencer_ak);
    delete(ak);
    return 0;
}

上面代码已经完成了修饰模式的任务,还可以通过策略模式进一步优化,可以更换消音器的种类。

#include <iostream>
using namespace std;

class Gun {
public:
    virtual void shoot() = 0;
};

class M16 : public Gun {
public:
    void shoot() override {
        cout << "M16 射击" << endl;
    }
};

class AK : public Gun {
public:
    void shoot() override {
        cout << "AK 射击" << endl;
    }
};

class AWM : public Gun {
public:
    void shoot() override {
        cout << "AWM 射击" << endl;
    }
};

//新增代码
//带装备的枪抽象类
class DecorateGun : public Gun {
public:
    DecorateGun(Gun *gun) : gun(gun) {}

protected:
    Gun *gun;
};

//新增消音器
//消音器抽象类,策略模式优化。
class Silencer {
public:
    virtual void silence() {
        cout << "默认没有安装消音器" << endl;
    }
};

class Silencer1 : public Silencer {
public:
    void silence() override {
        cout << "枪的声音变小了1" << endl;
    }
};

class Silencer2 : public Silencer {
public:
    void silence() override {
        cout << "枪的声音变小了2" << endl;
    }
};

class SilencerGun : public DecorateGun {
public:
    SilencerGun(Gun *gun, Silencer *silencer) : DecorateGun(gun), silencer(silencer) {}
    void shoot() override {
        silencer->silence();
        gun->shoot();
    }

    void setSilencer(Silencer *silencer) {
        this->silencer = silencer;
    }

private:
    Silencer *silencer;
};

int main()
{
    Silencer no_silencer;

    auto *ak = new AK;
    ak->shoot();

    auto *silencer_ak = new SilencerGun(ak, &no_silencer);
    silencer_ak->shoot();

    auto siliencer = new Silencer1;
    silencer_ak->setSilencer(siliencer);
    silencer_ak->shoot();

    //注意释放顺序,不要出现指针悬挂。
    delete(silencer_ak);
    delete(siliencer);
    delete(ak);
    return 0;
}

修饰模式稳定部分是:Gun/Decorate类,易变部分是它们的子类。

关键在于:修饰物(消音器)可以修饰不同的被修饰物(枪),需要组合关系来运行时决定;但被修饰的物体(带消音器的枪)也需要与枪又相同的接口,所有需要继承关系编译时已经可以决定。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值