本系列所有文章来自李建忠老师的设计模式笔记,系列如下:
设计模式(一)面向对象设计原则
23种设计模式(二)组件协作之模板方法
23种设计模式(三)组件协作之策略模式
23种设计模式(四)组件协作之观察者模式
23种设计模式(五)单一职责之装饰模式
23种设计模式(六)单一职责之桥模式
23种设计模式(七)对象创建之工厂方法
23种设计模式(八)对象创建之抽象工厂
23种设计模式(九)对象创建之原型模式
23种设计模式(十)对象创建之构建器
23种设计模式(十一)对象性能之单件模式
23种设计模式(十二)对象性能之享元模式
23种设计模式(十三)接口隔离之门面模式
23种设计模式(十四)接口隔离之代理模式
23种设计模式(十五)接口隔离之适配器
23种设计模式(十六)接口隔离之中介者
23种设计模式(十七)状态变化之状态模式
23种设计模式(十八)状态变化之备忘录
23种设计模式(十九)数据结构之组合模式
23种设计模式(二十)数据结构之迭代器
23种设计模式(二十一)数据结构之职责链
23种设计模式(二十二)行为变化之命令模式
23种设计模式(二十三)行为变化之访问器
23种设计模式(二十四)领域规则之解析器

文章目录

  • 动机
  • 设计方法一
  • 模式定义
  • 要点总结

  装饰模式属于一个新的类别,单一职责模式。同样属于单一职责模式的还有桥模式。

  所谓的单一职责模式说的是:在软件组件的设计中,如果责任划分的不清晰,使用继承得到的结果往往是随着需求的变化,子类急剧膨胀,同时充斥着重复代码,这时候的关键是划清责任。

  并不是说别的模式没有职责模式问题,而是装饰模式桥模式在单一职责模式问题上表现得比较特殊。

动机

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

设计方法一

  假设我们有一个IO的操作,有文件流、网络流、内存流、还有一些加密等等:

  • decorator1.cpp
//业务操作
class Stream{public:virtual char Read(int number)=0;virtual void Seek(int position)=0;virtual void Write(char data)=0;virtual ~Stream(){}
};//主体类
class FileStream: public Stream{public:virtual char Read(int number){//读文件流}virtual void Seek(int position){//定位文件流}virtual void Write(char data){//写文件流}};class NetworkStream :public Stream{public:virtual char Read(int number){//读网络流}virtual void Seek(int position){//定位网络流}virtual void Write(char data){//写网络流}};class MemoryStream :public Stream{public:virtual char Read(int number){//读内存流}virtual void Seek(int position){//定位内存流}virtual void Write(char data){//写内存流}};//扩展操作
class CryptoFileStream :public FileStream{public:virtual char Read(int number){//额外的加密操作...FileStream::Read(number);//读文件流}virtual void Seek(int position){//额外的加密操作...FileStream::Seek(position);//定位文件流//额外的加密操作...}virtual void Write(byte data){//额外的加密操作...FileStream::Write(data);//写文件流//额外的加密操作...}
};class CryptoNetworkStream : :public NetworkStream{public:virtual char Read(int number){//额外的加密操作...NetworkStream::Read(number);//读网络流}virtual void Seek(int position){//额外的加密操作...NetworkStream::Seek(position);//定位网络流//额外的加密操作...}virtual void Write(byte data){//额外的加密操作...NetworkStream::Write(data);//写网络流//额外的加密操作...}
};class CryptoMemoryStream : public MemoryStream{public:virtual char Read(int number){//额外的加密操作...MemoryStream::Read(number);//读内存流}virtual void Seek(int position){//额外的加密操作...MemoryStream::Seek(position);//定位内存流//额外的加密操作...}virtual void Write(byte data){//额外的加密操作...MemoryStream::Write(data);//写内存流//额外的加密操作...}
};class BufferedFileStream : public FileStream{//...
};class BufferedNetworkStream : public NetworkStream{//...
};class BufferedMemoryStream : public MemoryStream{//...
}class CryptoBufferedFileStream :public FileStream{public:virtual char Read(int number){//额外的加密操作...//额外的缓冲操作...FileStream::Read(number);//读文件流}virtual void Seek(int position){//额外的加密操作...//额外的缓冲操作...FileStream::Seek(position);//定位文件流//额外的加密操作...//额外的缓冲操作...}virtual void Write(byte data){//额外的加密操作...//额外的缓冲操作...FileStream::Write(data);//写文件流//额外的加密操作...//额外的缓冲操作...}
};void Process(){//编译时装配CryptoFileStream *fs1 = new CryptoFileStream();BufferedFileStream *fs2 = new BufferedFileStream();CryptoBufferedFileStream *fs3 =new CryptoBufferedFileStream();}

  上述代码的框架可表示为如下形式:

  上述设计的问题在于代码冗余。

  • decorator2.cpp
//业务操作
class Stream{public:virtual char Read(int number)=0;virtual void Seek(int position)=0;virtual void Write(char data)=0;virtual ~Stream(){}
};//主体类
class FileStream: public Stream{public:virtual char Read(int number){//读文件流}virtual void Seek(int position){//定位文件流}virtual void Write(char data){//写文件流}};class NetworkStream :public Stream{public:virtual char Read(int number){//读网络流}virtual void Seek(int position){//定位网络流}virtual void Write(char data){//写网络流}};class MemoryStream :public Stream{public:virtual char Read(int number){//读内存流}virtual void Seek(int position){//定位内存流}virtual void Write(char data){//写内存流}};//扩展操作
class CryptoStream: public Stream {Stream* stream;//...public:CryptoStream(Stream* stm):stream(stm){}virtual char Read(int number){//额外的加密操作...stream->Read(number);//读文件流}virtual void Seek(int position){//额外的加密操作...stream::Seek(position);//定位文件流//额外的加密操作...}virtual void Write(byte data){//额外的加密操作...stream::Write(data);//写文件流//额外的加密操作...}
};class BufferedStream : public Stream{Stream* stream;//...public:BufferedStream(Stream* stm):stream(stm){}//...
};void Process(){//运行时装配FileStream* s1=new FileStream();CryptoStream* s2=new CryptoStream(s1);BufferedStream* s3=new BufferedStream(s1);BufferedStream* s4=new BufferedStream(s2);
}
  • decorator3.cpp
//业务操作
class Stream{public:virtual char Read(int number)=0;virtual void Seek(int position)=0;virtual void Write(char data)=0;virtual ~Stream(){}
};//主体类
class FileStream: public Stream{public:virtual char Read(int number){//读文件流}virtual void Seek(int position){//定位文件流}virtual void Write(char data){//写文件流}};class NetworkStream :public Stream{public:virtual char Read(int number){//读网络流}virtual void Seek(int position){//定位网络流}virtual void Write(char data){//写网络流}};class MemoryStream :public Stream{public:virtual char Read(int number){//读内存流}virtual void Seek(int position){//定位内存流}virtual void Write(char data){//写内存流}};//扩展操作DecoratorStream: public Stream{protected:Stream* stream;//...DecoratorStream(Stream * stm):stream(stm){}};class CryptoStream: public DecoratorStream {public:CryptoStream(Stream* stm):DecoratorStream(stm){}virtual char Read(int number){//额外的加密操作...stream->Read(number);//读文件流}virtual void Seek(int position){//额外的加密操作...stream::Seek(position);//定位文件流//额外的加密操作...}virtual void Write(byte data){//额外的加密操作...stream::Write(data);//写文件流//额外的加密操作...}
};class BufferedStream : public DecoratorStream{Stream* stream;//...public:BufferedStream(Stream* stm):DecoratorStream(stm){}//...
};void Process(){//运行时装配FileStream* s1=new FileStream();CryptoStream* s2=new CryptoStream(s1);BufferedStream* s3=new BufferedStream(s1);BufferedStream* s4=new BufferedStream(s2);
}

  改进之后的代码框架可表示为:

模式定义

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

要点总结

  通过采用组合而非继承的手法, Decorator模式实现了在运行时动态扩展对象功能的能力,而且可以根据需要扩展多个功能。避免了使用继承带来的“灵活性差”和“多子类衍生问题”。

  Decorator类在接口上表现为is-a Component的继承关系,即Decorator类继承了Component类所具有的接口。但在实现上又表现为has-a Component的组合关系,即Decorator类又使用了另外一个Component类。

  Decorator模式的目的并非解决“多子类衍生的多继承”问题,Decorator模式应用的要点在于解决“主体类在多个方向上的扩展功能”——是为“装饰”的含义。

23种设计模式(五)单一职责之装饰模式相关推荐

  1. Java实现23种设计模式(五):桥接模式

    二十三种设计模式分类 一.概述 桥接(Bridge)模式的定义如下:将抽象与实现分离,使它们可以独立变化.它是用组合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度.桥接模式主要想实 ...

  2. 详解23种设计模式(基于Java)—— 结构型模式(三 / 五)

    目录 3.结构型模式(7种) 3.1.代理模式 3.1.1.概述 3.1.2.结构 3.1.3.静态代理 3.1.4.JDK动态代理 3.1.5.CGLIB动态代理 3.1.6.三种代理的对比 3.1 ...

  3. 五分钟精通设计模式(一)--速记23种设计模式

    本文由程序员伟哥原创,若需要转载,请注明出处. 通过我杜撰的一个新白娘子传奇故事帮助大家记忆23种设计模式 三类设计模式: 三类设计模式可以这么记: 一.白素贞闯入人满为患的大街上(闯街--创建) 刚 ...

  4. 【设计模式】Java 23种设计模式对比总结

    一.设计模式的分类 创建型模式,共五种(1-5):工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种(6-12):适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组 ...

  5. JAVA六大设计原则 和 23种设计模式

    相关书籍:<大话设计模式>.<Java设计模式>.<设计模式之禅>.<研磨设计模式>.<Head First 设计模式> JAVA六大设计原 ...

  6. 23种设计模式之单例模式、工厂模式、原型模式、建造者模式

    系列文章目录 第一章:程序设计原则-单一职责.接口隔离.依赖倒置.里式替换 第二章:程序设计原则-开闭原则.迪米特法则.合成复用原则 文章目录 系列文章目录 一.设计模式简单介绍 1.1.什么是设计模 ...

  7. JAVA设计模式总结之23种设计模式(重点!!!)

    JAVA设计模式总结之23种设计模式: 一.什么是设计模式 设计模式遵循的原则有6个: 二.设计模式的三个分类 三.各分类中模式的关键点 四.概说23种设计模式 1.单例模式(Singleton) 2 ...

  8. java 23种设计模式详解

    1. 软件设计模式意义 文章链接:http://c.biancheng.net/design_pattern/     设计模式的本质是对面向对象设计原则运用,是对类的封装.继承和多态以及类的关联关系 ...

  9. 23种设计模式-个人笔记(二)

    目录 五.23 种设计模式 1.单例模式 1.1.单例模式的定义与特点 1.2.单例模式的优点和缺点 1.3.单例模式的应用场景 1.4.单例模式的结构与实现 1.5.八种方式详解 1.6.单例模式在 ...

  10. 软件工程23种设计模式全解析

    23种设计模式全解析 一.设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代 ...

最新文章

  1. html 甘特图_甘特图该如何部署
  2. 笔记-项目立项管理-项目论证的程序
  3. luogu P3241 [HNOI2015]开店
  4. How Many Tables
  5. 火山小视频尼尔森:2019新线消费市场人群洞察报告(附下载)
  6. Linux学习命令总结个人及个人心得
  7. 包含图片,复选框的ListView(转)
  8. SDNU 1272.SL的秘密
  9. suse linux11下的多网口位置确定
  10. python中的rt_TensorRT学习总结
  11. 1024程序员节节日快乐
  12. 苹果库乐队怎么玩_iPhone技巧丨苹果手机制作炫酷铃声,就是不一样!
  13. 微信小店怎么设置优惠券
  14. 驱动中同步与异步发送IRP
  15. ros多个小乌龟_Ros 小乌龟节点启动
  16. rsem比对_链特异性参数设不对 结果全是错的
  17. 七、C/C++指针(易懂易学习,附代码案例)
  18. 商业银行个人客户价值指标体系
  19. WRF模式与Python 融合技术及精美绘图(包含前后处理及自动化运行)
  20. Windows部署服务(WDS)

热门文章

  1. 【管理心得之二十一】管得少就是管得好
  2. 在CentOS 7系统上安装PHP 7.4版本的方法
  3. Leetcode 刷题笔记(十八) —— 二叉树篇之二叉搜索树的修改与构造
  4. CTF中基本的Xor解密操作
  5. 局域网IP被抢占后如何强制夺回
  6. [转]在Windows server 2012上部署DPM 2012 SP1 RTM之先决条件准备
  7. java web 学习 --第八天(Java三级考试)
  8. logstash采集中文乱码
  9. 多种负载均衡算法及其Java代码实现
  10. Android深入四大组件(一)应用程序启动过程