C++设计模式:装饰器模式(四)

这篇具有很好参考价值的文章主要介绍了C++设计模式:装饰器模式(四)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、定义与动机
  • 装饰器模式定义:动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)。

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。

  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响降到最低?

  • 装饰器模式有一个很独特的地方:不仅继承接口(is a)、还组合接口(has a);继承接口是为了重写接口实现接口的方法,组合是为了动态装入接口的其他子类,这样就可以轻松的实现功能拓展,但又不违背单一职责原则!

2、案例分析
  • C++中的文件流对象并没有Java中的那么丰富,在Java语言中存在各种各样的流对象,基类有InputStream/OutputStream、Reader/Writer等等
  • 同时派生出各种IO流类,通过不同的功能、作用、辅助分类可以分很多种:文件流、对象流、缓冲流、缓冲文件流、加密缓冲流、等等
  • 如果代码都单纯的靠继承来实现Java庞大的IO流类库,工作量是非常大的。
  • 导致工作量巨大的原因:单纯通过继承来实现,存在大量的CV代码

C++设计模式:装饰器模式(四),设计模式,c++,设计模式,装饰器模式

2.1、基础实现
  • 普通的实现方式就是一直继承,代码无线重复的去设计实现
  • 里氏替换原则:当继承基类或者父类的代码大量被重写时,继承失去其原本的意义,换句话说可以不需要继承。
  • 这样设计会导致继承失去其原本的意义,因为大量的代码都被重写(违背里氏替换原则)
class Stream{
    virtual char Read(int n) = 0;
    virtual void Seek(int n) = 0;
    virtual void Write(char data) = 0;
    virtual ~Stream(){}
};
/*
 * FileStream、NetWorkStream、MemoryStream、ObjectStream...
 */
class FileStream: public Stream{
public:
    virtual char Read(int n){
        // 读文件流
    }
    virtual void Seek(int n){
        // 定位文件流
    }
    virtual void Write(char data){
        // 写文件流
    }
};

class NetWorkStream: public Stream{
public:
    virtual char Read(int n){
        // 读网络流
    }
    virtual void Seek(int n){
        // 定位网络流
    }
    virtual void Write(char data){
        // 写网络流
    }
};

// CryptoFileStream、CryptoNetWorkStream、CryptoMemoryStream、CryptoObjectStream...
class CryptoFileStream: public FileStream{
public:
    virtual char Read(int n){
        // 加密
        FileStream::Read(n);
        // 加密
    }
    virtual void Seek(int n){
        // 加密
        FileStream::Seek(n);
        // 加密
    }
    virtual void Write(char data){
        // 加密
        FileStream::Write(n);
        // 加密
    }
};
class CryptoNetWorkStream: public NetWorkStream{
public:
    virtual char Read(int n){

    }
    virtual void Seek(int n){

    }
    virtual void Write(char data){

    }
};

// BufferedFileStream、BufferedNetWorkStream、BufferedMemoryStream、BufferedObjectStream...
class BufferedFileStream: public FileStream{
    // ...
};
class BufferedNetWorkStream: public NetWorkStream{
    // ...
};

// CryptoBufferedFileStream、CryptoBufferedNetWorkStream、CryptoBufferedMemoryStream、CryptoBufferedObjectStream...
class CryptoBufferedFileStream: public BufferedFileStream{
    virtual char Read(int n){
        // 加密
        // 缓存
        BufferedFileStream::Read(n);
    }
    virtual void Seek(int n){
        //...
    }
    virtual void Write(char data){
        //...
    }
};
  • 而这样编写到了后期持续的扩展,类的数量指数增长,代码量急剧上升

C++设计模式:装饰器模式(四),设计模式,c++,设计模式,装饰器模式

2.2、普通装饰器
  • 为了消除这些冗余的代码,可以优先考虑使用组合的形式来取代靠继承实现的这些IO流类
  • 基于上述代码,只要灵活使用多态和组合就可以省略掉很多冗余的代码
    • CryptoStream类中组合一个Stream抽象类的指针,当构造CryptoStream类时可以通过传入FileStream、NetWorkStream对象来完成动态绑定,然后CryptoFileStream、CryptoNetWorkStream…其内部所有的方法都一样(因为只是基于不同的流类套了一层加密,而具体哪个流类通过Stream抽象类接口来动态绑定),因此可以代码去重。
  • 因此这样就可以实现去重
class Stream{
    virtual char Read(int n) = 0;
    virtual void Seek(int n) = 0;
    virtual void Write(char data) = 0;
    virtual ~Stream(){}
};
/*
 * FileStream、NetWorkStream、MemoryStream、ObjectStream...
 */
class FileStream: public Stream{
public:
    virtual char Read(int n){
        // 读文件流
    }
    virtual void Seek(int n){
        // 定位文件流
    }
    virtual void Write(char data){
        // 写文件流
    }
};

class NetWorkStream: public Stream{
public:
    virtual char Read(int n){
        // 读网络流
    }
    virtual void Seek(int n){
        // 定位网络流
    }
    virtual void Write(char data){
        // 写网络流
    }
};

// CryptoFileStream、CryptoNetWorkStream、CryptoMemoryStream、CryptoObjectStream...
class CryptoStream: public Stream{
private:
    Stream *stream;             // new FileStream()、new NetWorkStream().....
public:
    CryptoStream(Stream *_stream): stream(_stream){
        
    }
    virtual char Read(int n){
        // 加密
        stream->Read(n);
        // 加密
    }
    virtual void Seek(int n){
        // 加密
        stream->Read(n);
        // 加密
    }
    virtual void Write(char data){
        // 加密
        stream->Read(n);
        // 加密
    }
};

// BufferedFileStream、BufferedNetWorkStream、BufferedMemoryStream、BufferedObjectStream...
class BufferedStream: public Stream{
    Stream *stream;
    // ...
};

// CryptoBufferedFileStream、CryptoBufferedNetWorkStream、CryptoBufferedMemoryStream、CryptoBufferedObjectStream...
class CryptoBufferedStream: public Stream{
    Stream *stream;             //....
    virtual char Read(int n){
        // 加密
        // 缓存
    }
    virtual void Seek(int n){
        //...
    }
    virtual void Write(char data){
        //...
    }
};

void process()
{
    // 运行时装配
    FileStream fileStream = new FileStream();
    CryptoStream cryptoStream1 = new CryptoStream(new FileStream());
    CryptoStream cryptoStream2 = new CryptoStream(new NetWorkStream());
    ....    
    CryptoBufferedStream cryptoBufferedStream = new CryptoBufferedStream(new FileStream());
}
2.3、抽象装饰器
  • 抽象装饰器就是在实现类和基类之间套了一个装饰器类
    • 装饰器类负责继承基类,通过多态的动态绑定来运行时确定加载某个类
    • 实现类通过继承装饰器类,调用装饰器类中的对象完成操作
class Stream{
    virtual char Read(int n) = 0;
    virtual void Seek(int n) = 0;
    virtual void Write(char data) = 0;
    virtual ~Stream(){}
};
/*
 * FileStream、NetWorkStream、MemoryStream、ObjectStream...
 */
class FileStream: public Stream{
public:
    virtual char Read(int n){
        // 读文件流
    }
    virtual void Seek(int n){
        // 定位文件流
    }
    virtual void Write(char data){
        // 写文件流
    }
};

class NetWorkStream: public Stream{
public:
    virtual char Read(int n){
        // 读网络流
    }
    virtual void Seek(int n){
        // 定位网络流
    }
    virtual void Write(char data){
        // 写网络流
    }
};

class DecoratorStream: Stream{
protected:
    Stream *stream;
    DecoratorStream(Stream *_stream): stream(_stream){

    }
};

// CryptoFileStream、CryptoNetWorkStream、CryptoMemoryStream、CryptoObjectStream...
class CryptoStream: public DecoratorStream{
public:
    CryptoStream(Stream *_stream): DecoratorStream(_stream){

    }
    virtual char Read(int n){
        // 加密
        stream->Read(n);
        // 加密
    }
    virtual void Seek(int n){
        // 加密
        stream->Read(n);
        // 加密
    }
    virtual void Write(char data){
        // 加密
        stream->Read(n);
        // 加密
    }
};

// BufferedFileStream、BufferedNetWorkStream、BufferedMemoryStream、BufferedObjectStream...
class BufferedStream: public DecoratorStream{
    // ...
};

// CryptoBufferedFileStream、CryptoBufferedNetWorkStream、CryptoBufferedMemoryStream、CryptoBufferedObjectStream...
class CryptoBufferedStream: public DecoratorStream{
    virtual char Read(int n){
        // 加密
        // 缓存
    }
    virtual void Seek(int n){
        //...
    }
    virtual void Write(char data){
        //...
    }
};

void process()
{
    // 运行时装配
    FileStream fileStream = new FileStream();
    CryptoStream cryptoStream1 = new CryptoStream(new FileStream());
    CryptoStream cryptoStream2 = new CryptoStream(new NetWorkStream());
    ....
    CryptoBufferedStream cryptoBufferedStream = new CryptoBufferedStream(new FileStream());
}

C++设计模式:装饰器模式(四),设计模式,c++,设计模式,装饰器模式文章来源地址https://www.toymoban.com/news/detail-847861.html

4、总结
  • 通过采用组合而非继承的手法,Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能,避免了使用继承带来的“灵活性差”和“多子类衍生问题”。
  • Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所有具有的接口;但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component实现类。
  • Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”—是为“装饰”的含义
    C++设计模式:装饰器模式(四),设计模式,c++,设计模式,装饰器模式

到了这里,关于C++设计模式:装饰器模式(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式——装饰器模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。 这种模式创建了一个装饰类,用来包装原有的

    2024年02月10日
    浏览(37)
  • 【设计模式】-装饰器模式

    在软件开发中,经常有需求对已有的对象进行功能的扩展,但是传统的继承方式会导致类的数量快速增多,且难以维护。为了解决这个问题,装饰器模式应运而生。 装饰器模式是一种结构型设计模式,它可以在运行时动态地将新的行为附加到对象上,而不改变其结构。这种方

    2024年02月14日
    浏览(34)
  • 【设计模式】装饰器模式

    装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。 装饰器模式通过将对象包装在装饰器类中,以便动态地修改其行为。 这种模式创建了一个装饰类,用来包装原有的

    2024年02月13日
    浏览(37)
  • 设计模式--装饰者模式

    (1) 可乐种类/单品可乐 :BaiShiCola(百事可乐) FeiChangCola(非常可乐) CoCola(可口可乐) (2) 调料/附品: Milk  Chocolate (3) 要求在扩展新的可乐种类时 要具有良好的扩展性 改动方便 维护方便 (4) 使用OO的来就算不同之类可乐的费用 客户可以点单品可乐 也可以单品可乐+调料组合 方案1 

    2024年02月02日
    浏览(39)
  • 设计模式——装饰者模式

    更多内容,前往 IT-BLOG 现实生活中常常需要给某类产品动态增加新的功能,如:给面条各种调味品。在软件开发过程中,有时想用一些现存的组件。这些组件可能只是完成一些核心功能。但在不改变其架构的情况下,可以动态地扩展其功能。所以这些都可以采用装饰模式来实

    2024年02月22日
    浏览(32)
  • 设计模式(3)装饰模式

    一、介绍: 1、应用场景:把所需的功能按正确的顺序串联起来进行控制。动态地给一个对象添加一些额外的职责,就增加功能来说,装饰模式比生成子类更加灵活。 当需要给一个现有类添加附加职责,而又不能采用生成子类的方法进行扩充时。例如,该类被隐藏或者该类是

    2024年02月13日
    浏览(38)
  • 设计模式-装饰器模式

    装饰者模式的定义为:动态的给一个对象添加其它功能。 从扩展性来说,这种方式比继承更有弹性,更加灵活,装饰者模式也体现了开闭原则(OCP)。 星巴克咖啡订单项目(咖啡馆) : 1)咖啡种类/单品咖啡: Espresso(意大利浓咖啡)、ShortBlack、Decaf(无因咖啡)、LongBlack(美式咖啡) 2)

    2024年02月06日
    浏览(38)
  • Java设计模式-装饰模式

    装饰模式在Java领域是一种常见的设计模式,它能够在不改变对象原有结构的情况下,动态地为对象添加新的功能。它通过封装原有对象,在运行时动态地为对象添加新的行为或者修改原有行为,以扩展对象的功能。这种方式避免了继承的静态特性,让对象的行为可以根据需要

    2024年02月04日
    浏览(41)
  • 【前端设计模式】之装饰模式

    装饰模式(Decorator Pattern)是一种结构型设计模式,它允许在不改变原有对象结构的情况下,动态地给对象添加额外的功能。装饰模式通过创建一个包装器(装饰器)来包裹原有对象,并在保持接口一致性的前提下,增加新的行为或修改原有行为。 继承或实现相同的接口 :装

    2024年02月09日
    浏览(34)
  • 设计模式7:装饰者模式

    官方说法:装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。 个人理解:原始接口功能不足,需要添加新方法,但是别的地方已经实现了原始接口,所以原始接口又不能直接添加方法。这时候可以采用持有原始类对象,并且添加新方法

    2024年02月12日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包