设计模式初探-装饰模式

装饰模式(DECORATOR模式),又称包装器Wrapper,属于对象结构型模式,用于动态地给一个对象添加一些额外的职责。就增加功能而言,Decorator模式比生成子类更为灵活。它通过使用对象之间的关联关系取代类之间的继承关系,引入的装饰类既可以调用被装饰类的方法,还可以添加新的业务逻辑,以达到扩充被装饰类的功能。装饰模式和适配器模式虽然都称为包装器,但两者还是不同的。装饰模式只是在原有对象的基础上增加新的职责,而不改变对外提供的接口。适配器模式用于解决接口之间的不兼容问题,必然会改变对外提供的接口。

一、使用场景

1、在不影响其他对象的情况下,以动态,透明的方式给单个对象添加职责。装饰模式采用对象组合而非类继承方式扩展功能,所以对于需要扩充的对象可以动态添加,切换,删除相应的职责而不影响其他对象。

2、处理那些可以撤销的职责,对于需要某项职责的对象只需关联相应的装饰对象即可。

3、当不能采用继承的方式对系统进行扩展或者采用继承不利于系统扩展和维护时。一种情况是系统中存在大量独立的扩展,为支持每一种扩展或者扩展之间的组合将产生大量的子类,使得子类数目呈爆炸性增长。另一种情况可能是因为类定义被隐藏或类不能被继承,比如Java中类定义为final类。

二、UML图

装饰模式uml

三、Java实现

[java]  view plain  copy
  1. package study.patterns.decorator;  
  2.   
  3. /** 
  4.  * 装饰模式:降低系统的耦合度,可以动态增加或删除对象的职责, 
  5.  * 并使得需要装饰的具体构件类和具体装饰类可以独立变化, 
  6.  * 以便增加新的具体构件类和具体装饰类。 
  7.  * 如果需要在原有系统中增加一个新的具体构件类或者新的具体装饰类, 
  8.  * 无须修改现有类库代码,只需将它们分别作为抽象构件类或者抽象装饰类的子类即可.  
  9.  * @author qbg 
  10.  */  
  11. public class DecoratorPattern {  
  12.     public static void main(String[] args) {  
  13.         String test = "test123";  
  14.         //使用默认装饰类和不使用装饰类效果一样  
  15.         IStream dStream = new StreamDecorator(new MemoryStream());  
  16.         dStream.write(test);  
  17.         String r0 = dStream.read();  
  18.         System.out.println("======使用默认装饰类:"+r0);  
  19.         //使用压缩装饰类  
  20.         IStream cStream = new CompressingStream(new MemoryStream());  
  21.         cStream.write(test);  
  22.         String r1 = cStream.read();  
  23.         System.out.println("======使用压缩装饰类:"+r1);  
  24.         //使用ASCII装饰类  
  25.         IStream aStream = new ASCII7Strem(new FileStream());   
  26.         aStream.write(test);  
  27.         String r2 = aStream.read();  
  28.         System.out.println("======使用ASCII装饰类:"+r2);  
  29.         //先使用ASCII装饰类进行编码转换,然后使用压缩装饰类进行压缩  
  30.         IStream caStream = new ASCII7Strem(new CompressingStream(new FileStream()));  
  31.         caStream.write(test);  
  32.         String r3 = caStream.read();  
  33.         System.out.println("======使用ASCII和压缩装饰类:"+r3);  
  34.     }  
  35. }  
  36. /** 
  37.  * I/O流接口 
  38.  */  
  39. interface IStream{  
  40.     /** 
  41.      * 读取流 
  42.      */  
  43.     public String read();  
  44.     /** 
  45.      * 写入流 
  46.      */  
  47.     public void write(String str);  
  48. }  
  49. /** 
  50.  * 流介质为内存型 
  51.  */  
  52. class MemoryStream implements IStream{  
  53.     private String stream;  
  54.     @Override  
  55.     public String read() {  
  56.         System.out.println("从内存中读取流...");  
  57.         return stream;  
  58.     }  
  59.   
  60.     @Override  
  61.     public void write(String stream) {  
  62.         System.out.println("往内存中写入流...");  
  63.         this.stream = stream;  
  64.     }  
  65. }  
  66. /** 
  67.  * 流介质为文件系统  
  68.  */  
  69. class FileStream implements IStream{  
  70.     private String stream;  
  71.     @Override  
  72.     public String read() {  
  73.         System.out.println("从文件中读取流...");  
  74.         return stream;  
  75.     }  
  76.   
  77.     @Override  
  78.     public void write(String stream) {  
  79.         System.out.println("往文件中写入流...");  
  80.         this.stream = stream;  
  81.     }  
  82.   
  83. }  
  84. /** 
  85.  * 流装饰默认实现类 
  86.  */  
  87. class StreamDecorator implements IStream{  
  88.     private IStream stream;  
  89.     public StreamDecorator(IStream stream){  
  90.         this.stream = stream;  
  91.     }  
  92.     @Override  
  93.     public String read() {  
  94.         return this.stream.read();  
  95.     }  
  96.     @Override  
  97.     public void write(String stream) {  
  98.         this.stream.write(stream);  
  99.     }  
  100. }  
  101. /** 
  102.  * 将流数据转换为7位ASCII码 
  103.  */  
  104. class ASCII7Strem  extends StreamDecorator{  
  105.     public ASCII7Strem(IStream stream) {  
  106.         super(stream);  
  107.     }  
  108.     @Override  
  109.     public void write(String stream) {  
  110.         super.write(toAscii7(stream));  
  111.     }  
  112.     /* 
  113.      * 额外职责 
  114.      */  
  115.     private String toAscii7(String stream){  
  116.         System.out.println("将数据转换为7位ASCII码");  
  117.         return "ASCII["+stream+"]";  
  118.     }  
  119. }  
  120. /** 
  121.  * 将流数据压缩  
  122.  */  
  123. class CompressingStream extends StreamDecorator{  
  124.   
  125.     public CompressingStream(IStream stream) {  
  126.         super(stream);  
  127.     }  
  128.     @Override  
  129.     public void write(String stream) {  
  130.         super.write(compress(stream));  
  131.     }  
  132.     /* 
  133.      * 额外职责 
  134.      */  
  135.     private String compress(String stream){  
  136.         System.out.println("压缩数据");  
  137.         return "压缩["+stream+"]";  
  138.     }  
  139. }  
运行结果:

[plain]  view plain  copy
  1. 往内存中写入流...  
  2. 从内存中读取流...  
  3. ======使用默认装饰类:test123  
  4. 压缩数据  
  5. 往内存中写入流...  
  6. 从内存中读取流...  
  7. ======使用压缩装饰类:压缩[test123]  
  8. 将数据转换为7位ASCII码  
  9. 往文件中写入流...  
  10. 从文件中读取流...  
  11. ======使用ASCII装饰类:ASCII[test123]  
  12. 将数据转换为7位ASCII码  
  13. 压缩数据  
  14. 往文件中写入流...  
  15. 从文件中读取流...  
  16. ======使用ASCII和压缩装饰类:压缩[ASCII[test123]]  

四、模式优缺点

优点:

1、 对于扩展一个对象的功能,装饰模式比继承更加灵活性,不会导致类的个数急剧增加。
2、可以通过一种动态的方式来扩展一个对象的功能,通过配置文件可以在运行时选择不同的具体装饰类,从而实现不同的行为。
3、可以对一个对象进行多次装饰,通过使用不同的具体装饰类以及这些装饰类的排列组合,可以创造出很多不同行为的组合,得到功能更为强大的对象。
4、具体构件类与具体装饰类可以独立变化,用户可以根据需要增加新的具体构件类和具体装饰类,原有类库代码无须改变,符合“开闭原则”。

5、避免在层次结构高层的类有太多的特征。高层的类越简单,其可扩展性,灵活性越好。可以定义一个简单的类,然后使用Decorator类给它逐渐添加功能。

缺点:

1、 使用装饰模式进行系统设计时将产生很多小对象,这些对象的区别在于它们之间相互连接的方式有所不同,而不是它们的类或者属性值有所不同,大量小对象的产生势必会占用更多的系统资源,在一定程序上影响程序的性能,也增大了学习系统的复杂度。
2、装饰模式提供了一种比继承更加灵活机动的解决方案,但同时也意味着比继承更加易于出错,排错也很困难,对于多次装饰的对象,调试时寻找错误可能需要逐级排查,较为繁琐。

3、Decorator与它的Component不一样,Decorator只是透明的包装,所以客户端使用时不应该依赖Decorator。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
04-26
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值