Decorator-装饰模式

动机

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?

模式定义

动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)。——《设计模式》GoF

结构

在这里插入图片描述

要点

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

如果看到一个类继承自一个父类,同时组合了一个相同父类的成员对象,可以怀疑使用了 Decorator 设计模式

代码

// 以流为例,流作为基类(相当于图中的Component),可以派生出网络流,文件流,内存流(相当于图中的ConcreteComponent);
// 根据是否加密,缓存,又可以派生出加密流,缓存流;
// 如果按照一般的写法,网络流又要派生出加密流,缓存流; 文件流也要派生出加密流,缓存流; 内存流也要派生出加密流,缓存流;
// 子类个数就会成倍的增加
// Decorator提供了一种减少子类的方法, 以此为例,将装饰类继承流基类 ,并聚合流基类,加密流和缓存流继承自装饰类(相当于图中的ConcreteDecorator)

#include <iostream>

using namespace std;

class Stream {
private:
    /* data */
public:
    virtual ~Stream() {}
    virtual void Read(int number)   = 0;
    virtual void Write(char data)   = 0;
    virtual void Seek(int position) = 0;
};

class NetworkStream : public Stream {
private:
    /* data */
public:
    virtual ~NetworkStream() {}
    virtual void Read(int number)
    {
        cout << "Read NetworkStream " << number << endl;
    }
    virtual void Write(char data)
    {
        cout << "Write NetworkStream " << data << endl;
    }
    virtual void Seek(int position)
    {
        cout << "Seek NetworkStream " << position << endl;
    }
};

class FileStream : public Stream {
private:
    /* data */
public:
    virtual ~FileStream() {}
    virtual void Read(int number)
    {
        cout << "Read FileStream " << number << endl;
    }
    virtual void Write(char data)
    {
        cout << "Write FileStream " << data << endl;
    }
    virtual void Seek(int position)
    {
        cout << "Seek FileStream " << position << endl;
    }
};

// class MemoryStream : public Stream ...


class Decorator {
private:
    Stream* m_stream;

protected:
    Decorator(Stream* stream)
    {
        m_stream = stream;
    }
    virtual ~Decorator() {}
    virtual void Read(int number)
    {
        m_stream->Read(number);
    }
    virtual void Write(char data)
    {
        m_stream->Write(data);
    }
    virtual void Seek(int position)
    {
        m_stream->Seek(position);
    }
};

class CryptoStream : public Decorator {
private:
    /* data */
public:
    CryptoStream(Stream* stream)
        : Decorator(stream)
    {
    }
    ~CryptoStream() {}
    virtual void Read(int number)
    {
        cout << "Crypto read stream " << number << endl;
        Decorator::Read(number);
    }
    virtual void Write(char data)
    {
        cout << "Crypto write stream " << data << endl;
        Decorator::Write(data);
    }
    virtual void Seek(int position)
    {
        cout << "Crypto seek stream " << position << endl;
        Decorator::Seek(position);
    }
};

// class BufferStream : public Decorator ...

void TestDecorator(void)
{
    CryptoStream a(new FileStream());
    a.Read(10);
    a.Seek(0);
    a.Write(1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值