码迷,mamicode.com
首页 > 其他好文 > 详细

Decorator模式

时间:2021-03-01 13:45:11      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:中间   操作   动态   组合   修改   针对   需要   work   额外   

动机:在软件设计过程中,如果责任划分不清楚,随着需求的变化,子类极具膨胀,同时充斥着相同的代码。这时候需要划清责任。

一个示例程序:

技术图片

 

 

 

  1 class Stream
  2 {
  3 public:
  4     virtual void read() = 0;
  5     virtual void write() = 0;
  6     virtual ~Stream() {}  7 };
  8 class FileStream :public Stream
  9 {
 10 public:
 11     virtual void read()
 12     {
 13         cout << "读文件流" << endl;
 14     }
 15     virtual void write()
 16     {
 17         cout << "写文件流" << endl;
 18     }
 19 };
 20 class NetworkStream :public Stream
 21 {
 22 public:
 23     virtual void read()
 24     {
 25         cout << "读网络流" << endl;
 26     }
 27     virtual void write()
 28     {
 29         cout << "写网络流" << endl;
 30     }
 31 };
 32 class MemoryStream :public Stream
 33 {
 34 public:
 35     virtual void read()
 36     {
 37         cout << "读内存流" << endl;
 38     }
 39     virtual void write()
 40     {
 41         cout << "写内存流" << endl;
 42     }
 43 };
 44 //加密文件流
 45 class CryptoFileStream :public FileStream
 46 {
 47 public:
 48     virtual void read()
 49     {
 50         FileStream::read();
 51         cout << "额外加密" << endl;
 52     }
 53     virtual void write()
 54     {
 55         FileStream::write();
 56         cout << "额外加密" << endl;
 57     }
 58 };
 59 //加密网络流
 60 class  CryptoNetworkStream :public NetworkStream
 61 {
 62 public:
 63 
 64     virtual void read()
 65     {
 66         NetworkStream::read();
 67         cout << "额外加密" << endl;
 68     }
 69     virtual void write()
 70     {
 71         NetworkStream::write();
 72         cout << "额外加密" << endl;
 73     }
 74 };
 75 //加密内存流
 76 class CryptoMemoryStream :public MemoryStream
 77 {
 78 public:
 79     virtual void read()
 80     {
 81         MemoryStream::read();
 82         cout << "额外加密" << endl;
 83     }
 84     virtual void write()
 85     {
 86         MemoryStream::write();
 87         cout << "额外加密" << endl;
 88     }
 89 };
 90 //缓存文件流
 91 class BufferFileStream :public FileStream
 92 {
 93 public:
 94     virtual void read()
 95     {
 96         cout << "缓存操作" << endl;
 97         FileStream::read();
 98     }
 99     virtual void write()
100     {
101         cout << "缓存操作" << endl;
102         FileStream::write();
103     }
104 };
105 //缓存网络流
106 class BufferNetworkStream :public NetworkStream
107 {
108 public:
109     virtual void read()
110     {
111         cout << "缓存操作" << endl;
112         NetworkStream::read();
113     }
114     virtual void write()
115     {
116         cout << "缓存操作" << endl;
117        NetworkStream::write();
118     }
119 };
120 //缓存内存流
121 class BufferMemoryFile :public MemoryStream
122 {
123 public:
124     virtual void read()
125     {
126         cout << "缓存操作" << endl;
127         MemoryStream::read();
128     }
129     virtual void write()
130     {
131         cout << "缓存操作" << endl;
132         MemoryStream::write();
133     }
134 };

  仔细分析这个程序会发现:第51、67、82行的加密操作不会因为read的内容不同而不同,都是一样的加密操作。第56、72、87行针对写进行的加密操作也是一样的,这就出现了代码冗余。重复的代码太多,就需要消除重复。

  第一步调整:将继承调整为组合。

 1 //加密文件流
 2 class CryptoFileStream 
 3 {
 4 public:
 5     virtual void read()
 6     {
 7         fstream->read();
 8         cout << "额外加密" << endl;
 9     }
10     virtual void write()
11     {
12         fstream->read();
13         cout << "额外加密" << endl;
14     }
15 private:
16     FileStream *fstream;
17 };
18 //加密网络流
19 class  CryptoNetworkStream 
20 {
21 public:
22 
23     virtual void read()
24     {
25         nstream->read();
26         cout << "额外加密" << endl;
27     }
28     virtual void write()
29     {
30         nstream->write();
31         cout << "额外加密" << endl;
32     }
33 private:
34     NetworkStream *nstream;
35 };
36 //加密内存流
37 class CryptoMemoryStream 
38 {
39 public:
40     virtual void read()
41     {
42         mstream-> read();
43         cout << "额外加密" << endl;
44     }
45     virtual void write()
46     {
47         mstream->write();
48         cout << "额外加密" << endl;
49     }
50 private:
51     MemoryStream *mstream;
52 };

  第51、37、16行的变量定义都是某一个类的子类,这时可以提取公因式,把他们都声明成基类的类型。

class CryptoFileStream 
{
public:
    virtual void read()
    {
        fstream->read();
        cout << "额外加密" << endl;
    }
    virtual void write()
    {
        fstream->read();
        cout << "额外加密" << endl;
    }
private:
    Stream *fstream;  // = new FileStream; 在未来运行时
};
//加密网络流
class  CryptoNetworkStream 
{
public:

    virtual void read()
    {
        nstream->read();
        cout << "额外加密" << endl;
    }
    virtual void write()
    {
        nstream->write();
        cout << "额外加密" << endl;
    }
private:
    Stream *nstream; // = new networkStream;
};
//加密内存流
class CryptoMemoryStream 
{
public:
    virtual void read()
    {
        mstream-> read();
        cout << "额外加密" << endl;
    }
    virtual void write()
    {
        mstream->write();
        cout << "额外加密" << endl;
    }
private:
    Stream *mstream;  // = new memorystream
};

  代码层面发现这三个类一样,不一样的是在注释上,在运行时的未来不一样。总的来说在编译时一样,运行时不一样,这时设计模式的真谛。

  将三类合一

//  stream基类为cryptostream定义了接口规范
class CryptoStream :public Stream
{
public:
CryptoStream(Stream*s):stream(s){}
virtual void read() { stream->read(); cout << "额外加密" << endl; } virtual void write() { stream->read(); cout << "额外加密" << endl; } private: Stream *stream; // = new FileStream....; 在未来运行时 //= new networkstream; // = new memorystream; };

  编译运行

FileStream * fstream = new FileStream;
CryptoStream *cs = new CryptoStream(fstream);
cs->read();
cs->write();

NetworkStream *nstream = new NetworkStream;
CryptoStream *cs2 = new CryptoStream(nstream);
cs2->read();
cs2->write();

MemoryStream *mstream = new MemoryStream;
CryptoStream *cs3 = new CryptoStream(mstream);
cs3->read();
cs3->write();

技术图片

 

  将bufferStream也做相同的修改

 1 class CryptoStream :public Stream
 2 {
 3 public:
 4     CryptoStream(Stream *s) :stream(s){}
 5     virtual void read()
 6     {
 7         stream->read();
 8         cout << "额外加密" << endl;
 9     }
10     virtual void write()
11     {
12         stream->write();
13         cout << "额外加密" << endl;
14     }
15 private:
16     Stream *stream;  // = new FileStream....; 在未来运行时
17 };
18 
19 
20 class BufferStream :public Stream
21 {
22 public:
23     BufferStream(Stream *s) :stream(s){}
24     virtual void read()
25     {
26         cout << "缓存操作" << endl;
27         stream->read();
28     }
29     virtual void write()
30     {
31         cout << "缓存操作" << endl;
32         stream->write();
33     }
34 private:
35     Stream *stream;  //= new 
36 };

  第35、16行相同,将他们提取放在一个中间类中。

class Decorate :public Stream
{
public:
    Decorate(Stream *s) :stream(s){}
protected:
    Stream *stream;
};
//加密...流  
class CryptoStream :public Decorate
{
public:
    CryptoStream(Stream *s) :Decorate(s){}
    virtual void read()
    {
        stream->read();
        cout << "额外加密" << endl;
    }
    virtual void write()
    {
        stream->write();
        cout << "额外加密" << endl;
    }
};


class BufferStream :public Decorate
{
public:
    BufferStream(Stream *s) :Decorate(s){}
    virtual void read()
    {
        cout << "缓存操作" << endl;
        stream->read();
    }
    virtual void write()
    {
        cout << "缓存操作" << endl;
        stream->write();
    }
 
};

  全部修改完成之后,类与类之间的关系变成下面这样。

技术图片

 

 总结:

  使用装饰模式的场景:在某些情况在,我会可能会过度的使用继承来扩展功能,由于继承为类型引入了静态特质(FileStream::read()),使其缺乏灵活性。随着功能的增多,会导致子类膨胀。

  用组合来替换继承,运行时动态扩展功能,消除重复代码。Decorator类即继承了基类(is a),有内含有基类指针(has a)

装饰模式的结构:

技术图片

 

 

 

 

   

Decorator模式

标签:中间   操作   动态   组合   修改   针对   需要   work   额外   

原文地址:https://www.cnblogs.com/xiaoxiaolinux/p/14458807.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!