c++设计模式-装饰器模式

c++设计模式-装饰器模式

一、我对装饰器模式的理解

1)通过包裹一个类(在该类的基础上,调用该类的方法,并加上一些附加的操作,并返回与该类继承自同一个基类的类(调用装饰器前后可以用同样的基类指针进行接收))

装饰器和被装饰的对象必须有完全一致的方法名。只是在装饰器的方法中会调用被装饰对象的同名方法
如果装饰器和被装饰的对象方法名不一致,那么将导致装饰之后的结果不能再次被另外一个装饰器装饰(因为方法名已经变了)

2)装饰器和待装饰的组件都继承自同一个基类,这点很重要

二.装饰器模式的c++实现

1、装饰器模板和组件(被装饰对象)的基类

Base class:装饰器模式的基类,(被装饰对象)组件和装饰器模板都需要继承自基类


    class Beverage
    {
    private:
     std::string description;
    public:
     Beverage() = default;
     Beverage(std::string des) //构造方法为了让组件继承,而不是为了让装饰器继承
     {
      this->description = des;
     }
     virtual std::string getDescription() //让组件继承,而不是为了让装饰器继承
     {
      return description;
     }
     virtual float cost() = 0; //让子类组件实现
    };

2、组件的定义

被装饰对象1:饮料1


    class OrangeJuice :public Beverage
    {
    public:
     OrangeJuice() :Beverage("Orange juice"){};
     float cost() override //子类组件实现具体cost方法
     {
      return 1.99;
     }
    };

被装饰对象2:饮料2


    class AppleJuice :public Beverage
    {
    public:
     AppleJuice() :Beverage("Apple juice"){};
     float cost() override //子类组件实现具体cost方法
     {
      return 2.99;
     }
    };

3、装饰器的定义

3.1装饰器模板的定义

装饰器模板_特别注意:也要继承base


    class Decorator :public Beverage
    {
    protected:
     std::shared_ptr<Beverage> ptr; //装饰器要保存当前装饰对象的指针,注意只用申明指针,而不需要给对象分配空间
    public:
     Decorator() = default;
     Decorator(std::shared_ptr<Beverage> p)
     {
      ptr=p;
     };
     std::string getDescription() override = 0; //装饰器不继承Beverage的任何方法,把父类覆盖的同时让其本身成为一个抽象接口
     float cost() override = 0; //装饰器不继承Beverage的任何方法,把父类覆盖的同时让其本身成为一个抽象接口
    };
3.2具体装饰器的定义

装饰器1:mocha


    class Mocha :public Decorator
    {
    public:
     Mocha(std::shared_ptr<Beverage> p) :Decorator(p){}; //相同的操作被抽象到基类中,直接委托给基类实现
     std::string getDescription() override //注意:装饰器的所有函数都是在被装饰对象函数的基础上进行操作的,因此初始化一个装饰器需要保存其装饰对象的指针
     {
      return ptr->getDescription() + ";" + "Mocha";
     }
     float cost() override
     {
      return ptr->cost() + 0.4;
     }
    };

装饰器2:Naiyou


    class Naiyou :public Decorator
    {
    public:
     Naiyou(std::shared_ptr<Beverage> p) :Decorator(p){};
     std::string getDescription() override
     {
      return ptr->getDescription() + ";" + "Naiyou";
     }
     float cost() override
     {
      return ptr->cost() + 0.8;
     }
    };

4、主函数:运用装饰器模式装饰对象


    #include "Beverage.h"
    #include <iostream>

    using namespace std;
    int main()
    {
    /*生成OrangeJuice和AppleJuice的对象,用基类对象指针指向*/
     shared_ptr<Beverage> orangeJuice = make_shared<OrangeJuice>();
     shared_ptr<Beverage> appleJuice = make_shared<AppleJuice>();
    /*生成Mocha对象,传入orangeJuice智能指针初始化(若传普通指针会报错),这样就Mocha对象就会装饰orangeJuice*/
     shared_ptr<Beverage> orangeJuiceWithMocha = make_shared<Mocha>(orangeJuice);
     shared_ptr<Beverage> orangeJuiceWithNaiyou = make_shared<Naiyou>(orangeJuice);
     shared_ptr<Beverage> orangeJuiceWithNaiyouAndMocha = make_shared<Naiyou>(orangeJuiceWithMocha);

     cout << "description:" << orangeJuiceWithMocha->getDescription() << endl
      << orangeJuiceWithMocha->cost() << endl;

     cout << "description:" << orangeJuiceWithNaiyou->getDescription() << endl
      << orangeJuiceWithNaiyou->cost() << endl;

     cout << "description:" << orangeJuiceWithNaiyouAndMocha->getDescription() << endl
      << orangeJuiceWithNaiyouAndMocha->cost() << endl;

     system("pause");
    }

编程经验

1)把子类中可能通用的操作尽可能放在父类中

2)C++中最好全部使用智能指针,而不要将传统指针和智能指针混用

3)不能把普通指针转换为智能指针,但智能指针可以转换为普通指针,所以要尽可能用智能指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值