前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >装饰模式C++实现(decorator)

装饰模式C++实现(decorator)

作者头像
里克贝斯
发布2021-05-21 11:45:17
4150
发布2021-05-21 11:45:17
举报
文章被收录于专栏:图灵技术域图灵技术域

简介

  • 动态地给一个对象添加一些额外的职责。
  • 就增加功能来说,装饰模式比生成子类更为灵活。

动机

  • 有时我们希望给某个对象而不是整个类添加一些功能。
  • 使用继承机制是添加功能的一种有效途径,但不够灵活,用户不能控制对组件添加功能的方式和时机。
  • 一种较为灵活的方式是将组件嵌入另一个对象中,由这个对象添加功能,我们称这个嵌入的对象为装饰。
  • 这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。

适用性

  • 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。
  • 处理那些可以撤销的职责。
  • 当不能采用生成子类的方法进行扩充时。
    • 可能有大量独立的扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
    • 类定义被隐藏,或类定义不能用于生成子类。

结构

装饰模式的参与者

  • Component
    • 定义一个对象接口,可以给这些对象动态地添加职责。
  • ConcreteComponent
    • 定义一个对象,可以给这个对象添加一些职责。
  • Decorator
    • 维持一个指向Component对象的指针,并定义一个与Component接口一致的接口。
  • ConcreteDecorator
    • 向组件添加职责。

装饰模式的协作

  • Decorator将请求转发给它的Component对象,并有可能在转发请求前后执行一些附加动作。

效果

  • 比静态继承更灵活
  • 避免在层次结构高层的类有太多的特征
  • Decorator与它的Component不一样
  • 有许多小对象

注意点

  • 如果只有一个ConcreteComponent类而没有Component类,那么Decorator类可以是ConcreteComponent的一个子类。
  • 同理,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator合并成一个类。

实例

给定两种初始的汽车类,例如丰田和沃尔沃,利用装饰模式分别给它们添加新的功能,其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。

UML图

代码与函数

Component:Car类

ConcreteComponent:TOYOTA、VOLOVO类

Decorator:Function类

ConcreteDecorator:Navigator、SelfDrive、VoiceControl类

C++

代码语言:javascript
复制
#include<iostream>
using namespace std;

/*
给定两种初始的汽车类,例如丰田和沃尔沃,
利用装饰模式分别给它们添加新的功能,
其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
*/

class Car{//Component
public:
    virtual void showInfo() = 0;
};

class TOYOTA: public Car{
public:
    TOYOTA(){}
    TOYOTA(string name){
        this->name = name;
    }
    void showInfo(){
        cout<<name<<endl;
    }
private:
    string name;
};

class  VOLOVO: public Car{
public:
    VOLOVO(){}
    VOLOVO(string name){
        this->name = name;
    }
    void showInfo(){
        cout<<name<<endl;
    }
private:
    string name;
};

class Function: public Car{//Decorator
protected:
    Car* car;
public:
    void Decorate(Car* car){
        this->car = car;
    }
    void showInfo(){
        if(car != NULL)car->showInfo();
    }
};

//其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。

class Navigator: public Function{
public:
    void showInfo(){
        cout<<"导航 ";
        Function::showInfo();
    }
};

class SelfDrive: public Function{
public:
    void showInfo(){
        cout<<"自动驾驶 ";
        Function::showInfo();
    }
};

class VoiceControl: public Function{
public:
    void showInfo(){
        cout<<"语音控制 ";
        Function::showInfo();
    }
};


//其中丰田可以导航和自动驾驶,沃尔沃可以导航和语音控制。
int main(){
    Car* toyota = new TOYOTA("丰田卡罗拉");
    Navigator* na = new Navigator();
    SelfDrive* sd = new SelfDrive();
    na->Decorate(toyota);
    sd->Decorate(na);
    sd->showInfo();
    cout<<endl;
    
    Car* volovo = new VOLOVO("沃尔沃S90");
    Navigator* na2 = new Navigator();
    VoiceControl* vc = new VoiceControl();
    na2->Decorate(volovo);
    vc->Decorate(na2);
    vc->showInfo();

    return 0;
}

总结

①本次实验通过Car的实例掌握并编码了装饰模式。

②注意如果只有一个ConcreteComponent类而没有Component类,那么Decorator类可以是ConcreteComponent的一个子类。在本次实验中,有TOYOTA和VOLOVO两个具体的类,因此需要一个Component的Car类来定义接口

③由②可知,如果只有一个ConcreteDecorator类,那么就没有必要建立一个单独的Decorator类,而可以把Decorator和ConcreteDecorator合并成一个类。在本次实验中有Navigator、SelfDrive、VoiceControl三个具体的装饰类。

④在客户端中,要最后一个添加的职责,用来是包装好了的车对象,因此需要由最后一个装饰的实例显示结果。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 动机
  • 适用性
  • 结构
    • 装饰模式的参与者
      • 装饰模式的协作
        • 效果
          • 注意点
          • 实例
            • UML图
              • 代码与函数
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档