请选择 进入手机版 | 继续访问电脑版
切换风格

Sunset glow Snow NewYear London Flowers Wizard California Cloud Sky Lavender City Black Beige Dragon

1万

主题

1万

帖子

4万

积分

管理员

Rank: 18Rank: 18Rank: 18Rank: 18Rank: 18

吾爱币
30058
在线时间
385 小时
注册时间
2019-8-16

论坛新星

设计模式 - 装饰模式[复制链接]
发表于 4 天前 | 显示全部楼层 |阅读模式
标签:width 操作 情况下 透明 loading 产生 应该 pre 活性
“单一职责”模式
在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。
典型模式
? Decorator
? Bridge


代码示例:
jia.gif jia.gif 1 //业务操作 2 class Stream{ 3 public 4 virtual char Read(int number)=0; 5 virtual void Seek(int position)=0; 6 virtual void Write(char data)=0; 7 8 virtual ~Stream(){} 9 }; 10 11 //主体类 12 class FileStream: public Stream{ 13 public: 14 virtual char Read(int number){ 15 //读文件流 16 } 17 virtual void Seek(int position){ 18 //定位文件流 19 } 20 virtual void Write(char data){ 21 //写文件流 22 } 23 24 }; 25 26 class NetworkStream :public Stream{ 27 public: 28 virtual char Read(int number){ 29 //读网络流 30 } 31 virtual void Seek(int position){ 32 //定位网络流 33 } 34 virtual void Write(char data){ 35 //写网络流 36 } 37 38 }; 39 40 class MemoryStream :public Stream{ 41 public: 42 virtual char Read(int number){ 43 //读内存流 44 } 45 virtual void Seek(int position){ 46 //定位内存流 47 } 48 virtual void Write(char data){ 49 //写内存流 50 } 51 52 }; 53 54 //扩展操作 55 class CryptoFileStream :public FileStream{ 56 public: 57 virtual char Read(int number){ 58 59 //额外的加密操作... 60 FileStream::Read(number);//读文件流 61 62 } 63 virtual void Seek(int position){ 64 //额外的加密操作... 65 FileStream::Seek(position);//定位文件流 66 //额外的加密操作... 67 } 68 virtual void Write(byte data){ 69 //额外的加密操作... 70 FileStream::Write(data);//写文件流 71 //额外的加密操作... 72 } 73 }; 74 75 class CryptoNetworkStream : :public NetworkStream{ 76 public: 77 virtual char Read(int number){ 78 79 //额外的加密操作... 80 NetworkStream::Read(number);//读网络流 81 } 82 virtual void Seek(int position){ 83 //额外的加密操作... 84 NetworkStream::Seek(position);//定位网络流 85 //额外的加密操作... 86 } 87 virtual void Write(byte data){ 88 //额外的加密操作... 89 NetworkStream::Write(data);//写网络流 90 //额外的加密操作... 91 } 92 }; 93 94 class CryptoMemoryStream : public MemoryStream{ 95 public: 96 virtual char Read(int number){ 97 98 //额外的加密操作... 99 MemoryStream::Read(number);//读内存流100 }101 virtual void Seek(int position){102 //额外的加密操作...103 MemoryStream::Seek(position);//定位内存流104 //额外的加密操作...105 }106 virtual void Write(byte data){107 //额外的加密操作...108 MemoryStream::Write(data);//写内存流109 //额外的加密操作...110 }111 };112113 class BufferedFileStream : public FileStream{114 //...115 };116117 class BufferedNetworkStream : public NetworkStream{118 //...119 };120121 class BufferedMemoryStream : public MemoryStream{122 //...123 }124125126127128 class CryptoBufferedFileStream :public FileStream{129 public:130 virtual char Read(int number){131132 //额外的加密操作...133 //额外的缓冲操作...134 FileStream::Read(number);//读文件流135 }136 virtual void Seek(int position){137 //额外的加密操作...138 //额外的缓冲操作...139 FileStream::Seek(position);//定位文件流140 //额外的加密操作...141 //额外的缓冲操作...142 }143 virtual void Write(byte data){144 //额外的加密操作...145 //额外的缓冲操作...146 FileStream::Write(data);//写文件流147 //额外的加密操作...148 //额外的缓冲操作...149 }150 };151152153154 void Process(){155156 //编译时装配157 CryptoFileStream *fs1 = new CryptoFileStream();158159 BufferedFileStream *fs2 = new BufferedFileStream();160161 CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();162163 }
decorator1.cpp
流stream作为一个基类有一些基础的方法,如read,write,seek
各种流文件流,网络流,内存流等继承于基类流,同时会有扩展的需求,如加密,且加密相同,只是读取的操作不一样,因此又会有新的不同流的扩展类继承于各种流。当然除了加密还会有其他的扩展操作如缓冲buffer,同理也可以像加密一样继承。
如果要对一种流既加密又缓冲,可以继承了流之后在读写方法中添加加密操作,缓冲,读流的基础操作。
以上的代码会有什么缺陷?






随着扩展方法的增加,由于对继承的不良使用,子类的规模不断膨胀,产生很多重复的代码。
改进一:使用组合
1 //业务操作 2 class Stream{ 3 4 public 5 virtual char Read(int number)=0; 6 virtual void Seek(int position)=0; 7 virtual void Write(char data)=0; 8 9 virtual ~Stream(){} 10 }; 11 12 //主体类 13 class FileStream: public Stream{ 14 public: 15 virtual char Read(int number){ 16 //读文件流 17 } 18 virtual void Seek(int position){ 19 //定位文件流 20 } 21 virtual void Write(char data){ 22 //写文件流 23 } 24 25 }; 26 27 class NetworkStream :public Stream{ 28 public: 29 virtual char Read(int number){ 30 //读网络流 31 } 32 virtual void Seek(int position){ 33 //定位网络流 34 } 35 virtual void Write(char data){ 36 //写网络流 37 } 38 39 }; 40 41 class MemoryStream :public Stream{ 42 public: 43 virtual char Read(int number){ 44 //读内存流 45 } 46 virtual void Seek(int position){ 47 //定位内存流 48 } 49 virtual void Write(char data){ 50 //写内存流 51 } 52 53 }; 54 55 //扩展操作 56 class CryptoStream: public Stream { 57 58 Stream* stream;//... 59 60 public: 61 CryptoStream(Stream* stm):stream(stm){ 62 63 } 64 65 66 virtual char Read(int number){ 67 68 //额外的加密操作... 69 stream->Read(number);//读文件流 70 } 71 virtual void Seek(int position){ 72 //额外的加密操作... 73 stream::Seek(position);//定位文件流 74 //额外的加密操作... 75 } 76 virtual void Write(byte data){ 77 //额外的加密操作... 78 stream::Write(data);//写文件流 79 //额外的加密操作... 80 } 81 }; 82 83 84 85 class BufferedStream : public Stream{ 86 87 Stream* stream;//... 88 89 public: 90 BufferedStream(Stream* stm):stream(stm){ 91 92 } 93 //... 94 }; 95 96 97 void Process(){ 98 99 //运行时装配100 FileStream* s1=new FileStream();101 CryptoStream* s2=new CryptoStream(s1);102103 BufferedStream* s3=new BufferedStream(s1);104105 BufferedStream* s4=new BufferedStream(s2);106107108109 }
decorator2.cpp
若多个子类含有相同的字段,那应该将该字段向上层提。
改进二:于是在创建一个中间类Decorator
1 //业务操作 2 class Stream{ 3 4 public 5 virtual char Read(int number)=0; 6 virtual void Seek(int position)=0; 7 virtual void Write(char data)=0; 8 9 virtual ~Stream(){} 10 }; 11 12 //主体类 13 class FileStream: public Stream{ 14 public: 15 virtual char Read(int number){ 16 //读文件流 17 } 18 virtual void Seek(int position){ 19 //定位文件流 20 } 21 virtual void Write(char data){ 22 //写文件流 23 } 24 25 }; 26 27 class NetworkStream :public Stream{ 28 public: 29 virtual char Read(int number){ 30 //读网络流 31 } 32 virtual void Seek(int position){ 33 //定位网络流 34 } 35 virtual void Write(char data){ 36 //写网络流 37 } 38 39 }; 40 41 class MemoryStream :public Stream{ 42 public: 43 virtual char Read(int number){ 44 //读内存流 45 } 46 virtual void Seek(int position){ 47 //定位内存流 48 } 49 virtual void Write(char data){ 50 //写内存流 51 } 52 53 }; 54 55 //扩展操作 56 57 DecoratorStream: public Stream{ 58 protected: 59 Stream* stream;//... 60 61 DecoratorStream(Stream * stm):stream(stm){ 62 63 } 64 65 }; 66 67 class CryptoStream: public DecoratorStream { 68 69 70 public: 71 CryptoStream(Stream* stm):DecoratorStream(stm){ 72 73 } 74 75 76 virtual char Read(int number){ 77 78 //额外的加密操作... 79 stream->Read(number);//读文件流 80 } 81 virtual void Seek(int position){ 82 //额外的加密操作... 83 stream::Seek(position);//定位文件流 84 //额外的加密操作... 85 } 86 virtual void Write(byte data){ 87 //额外的加密操作... 88 stream::Write(data);//写文件流 89 //额外的加密操作... 90 } 91 }; 92 93 94 95 class BufferedStream : public DecoratorStream{ 96 97 Stream* stream;//... 98 99 public:100 BufferedStream(Stream* stm):DecoratorStream(stm){101102 }103 //...104 };105106 void Process(){107108 //运行时装配109 FileStream* s1=new FileStream();110111 CryptoStream* s2=new CryptoStream(s1);112113 BufferedStream* s3=new BufferedStream(s1);114115 BufferedStream* s4=new BufferedStream(s2);116117118119 }
decorator3.cpp



在DecoratorStream中,使用组合的方式实现多态,包含了Stream基类。
装饰模式,动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更灵活。有时我们希望给某个对象而不是整个类添加一些功能。例如上面的例子,有一个文件流,允许对它添加加密或者缓冲的扩展功能。装饰模式下,会将文件流嵌入到另一个对象(Decorator)中,由该对象完成特性的添加,该嵌入的对象就成为装饰,这个装饰与它所装饰的组件接口一致,因此它对使用该组件的客户透明。
动机

  • 在某些情况下我们可能会“过度地使用继承来扩展对象的功能”,由于继承为类型引入的静态特质,使得这种扩展方式缺乏灵活性;并且随着子类的增多(扩展功能的增多),各种子类的组合(扩展功能的组合)会导致更多子类的膨胀。
  • 如何使“对象功能的扩展”能够根据需要来动态地实现?同时避免“扩展功能的增多”带来的子类膨胀问题?从而使得任何“功能扩展变化”所导致的影响将为最低?
继承引入的静态特性如下第七行:
1 //扩展操作 2 class CryptoFileStream :public FileStream{ 3 public: 4 virtual char Read(int number){ 5 6 //额外的加密操作... 7 FileStream::Read(number);//读文件流 8 } 9 ...10 }
组合引入的动态特性如下第八行:
1 class CryptoStream: public DecoratorStream { 2 3 public: 4 CryptoStream(Stream* stm):DecoratorStream(stm){ 5 6 } 7 8 virtual char Read(int number){ 9 //额外的加密操作...10 stream->Read(number);//读文件流11 }12 ...13 }
模式定义
动态(组合)地给一个对象增加一些额外的职责。就增加功能而言,Decorator模式比生成子类(继承)更为灵活(消除重复代码 & 减少子类个数)。
                              ——《设计模式》GoF





要点总结

  • 通过采用组合而非继承的手法, Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”
  • Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类
  • Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义
(若一个类继承了一个父类,且在字段里包含(组合)了该父类,很大可能就是Decorator设计模式,基类和组合在功能上由类似的地方,一般来说不会在一个类中同时继承和组合同一个类。但在装饰模式中,使用继承是为了完善基类stream接口的规范,使用组合是为了支持调用filestream,netstream中的接口)
装饰模式提供了更加灵活的向对象添加职责的方式。可以用添加和分离的方法,用装饰在运行时刻增加和删除职责。装饰模式提供了一种“即用即付”的方法来添加职责。它并不试图在一个复杂的可定制的类中支持所有可预见的特征,相反,你可以定义一个简单的类,并且用装饰类给它逐渐地添加功能。可以从简单的部件组合出复杂的功能

设计模式 - 装饰模式
标签:width 操作 情况下 透明 loading 产生 应该 pre 活性
原文地址:https://www.cnblogs.com/y4247464/p/14259058.html




上一篇:RHLE8 docker安装
下一篇:记一次内存泄露调试
回复

使用道具 举报

244

主题

3043

帖子

6331

积分

金牌会员

Rank: 6Rank: 6

吾爱币
3288
在线时间
0 小时
注册时间
2020-6-28

论坛新星

发表于 4 天前 | 显示全部楼层
支持,赞一个
回复

使用道具 举报

48

主题

2687

帖子

5422

积分

金牌会员

Rank: 6Rank: 6

吾爱币
2735
在线时间
0 小时
注册时间
2020-7-7
发表于 前天 07:21 | 显示全部楼层
锄禾日当午,发帖真辛苦。谁知坛中餐,帖帖皆辛苦!
回复

使用道具 举报

201

主题

3000

帖子

6201

积分

金牌会员

Rank: 6Rank: 6

吾爱币
3201
在线时间
0 小时
注册时间
2020-6-28

论坛新星

发表于 前天 21:53 | 显示全部楼层
顶起顶起顶起
回复

使用道具 举报

235

主题

3003

帖子

6241

积分

金牌会员

Rank: 6Rank: 6

吾爱币
3238
在线时间
0 小时
注册时间
2020-6-28

论坛新星

发表于 昨天 09:42 | 显示全部楼层
打酱油的人拉,回复下赚取积分
回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|Archiver|手机版|小黑屋|吾爱分享-享你所想 ( 黔ICP备18007665号-2 )|网站地图

GMT+8, 2021-1-17 07:01 , Processed in 3.468068 second(s), 97 queries .

Powered by 52Fenxiang.Top

© 2001-2020 Comsenz Inc.

返回顶部