设计模式总结篇系列:装饰器模式(Decorator)

简介:

在面向对象设计过程中,经常会遇到需要对现有的类的功能进行扩展,通常我们可以采用继承的方式。例如老罗最近在做手机,一开始需要定义手机所应具有的功能:

复制代码
1 interface Phone{
2     
3     public void tel();
4     
5     public void sms();
6     
7 }
复制代码

在此,为简单起见,只是定义了接打电话和收发短信功能。

然后,老罗开始造手机,经过两年艰苦努力,第一代手机T1终于面世了,很高兴的开了发布会,反响还不错。

复制代码
 1 class T1 implements Phone{
 2 
 3     @Override
 4     public void tel() {
 5         System.out.println("可以实现基本的接打电话");
 6     }
 7 
 8     @Override
 9     public void sms() {
10         System.out.println("可以实现基本的收发短信功能");
11     }
12     
13 }
复制代码

T1面世了,当然,只有不短的追求才有更大的进步的,在进一步的努力后,新一代的T2可以在T1的基础上实现安装Android软件的功能了。通常情况下,我们可能进行如下定义:

复制代码
1 class T2 extends T1{
2     
3     public void installApk(){
4         System.out.println("可以安装Android软件了");
5     }
6     
7 }
复制代码

显然,采取了继承的方式,T2在T1的基础上新增了自己所具有的更多功能——可以安装Android软件。这是一个进步。

又过了一段时间,老罗想出做手机不仅仅需要满足这些基本的功能,还应该最大程度上的最好用户体验,于是,目前最快的闪拍被想到了,此功能被加入到了最新一代的T3中。

复制代码
1 class T3 extends T2{
2     
3     public void fastestPhoto(){
4         System.out.println("可以实现目前最快的闪拍");
5     }
6     
7 }
复制代码

自然的,我们首先想到的还是通过继承的方式,在继承第2代基础上扩充了T3的功能。

当然,这是一件相当值得庆贺的事情。现在T1、T2、T3都面向市场推出了。由于市场需求较大,每一代的手机都在不断的制造中。现在有一个新的需求出来了,电信的用户反馈,这么手机都不支持电信卡,怎么办?

于是,老罗为了满足电信用户,急需在T2上推出相应的电信手机,那么现在怎么办呢?第一个想到的可能是修改T2类:

复制代码
 1 class T2 extends T1 {
 2 
 3     public void installApk() {
 4         System.out.println("可以安装Android软件了");
 5     }
 6 
 7     @Override
 8     public void tel() {
 9         supportDx();
10         System.out.println("可以实现基本的接打电话");
11     }
12 
13     @Override
14     public void sms() {
15         supportDx();
16         System.out.println("可以实现基本的收发短信功能");
17     }
18 
19     public void supportDx() {
20         System.out.println("可以支持电信用户了");
21     }
22 
23 }
复制代码

现在问题就出来了,由于继承关系的存在,虽然表面上只是修改了T2类,实际上其所有的子类都间接的被修改了。那么现在又有两个选择,要么修改其所有子类,这肯定不实际,要么不修改T2类,以免带来不必要的T2修改后对其所有子类的影响,但为了满足需求,可能得继承T2类新定义一个新的类,这样会导致类的无线膨胀问题(因为这种需求是不可预估的),那么有没有什么好的解决方案呢?

于是,基本包装/装饰而不是继承来实现此类场景的类的设计是一个不错的选择。由此带来的设计模式称之为"装饰模式"。

为了给一个现有的类增加一些新的功能,而不引其原来类的修改,用装饰模式去代替继承模式,要求装饰类和被装饰类实现同一接口,装饰对象有被装饰对象的实例。

那么我们具体看一下在上面场景中使用装饰模式如何设计类。

复制代码
 1 class T2 implements Phone {
 2 
 3     private Phone phone;
 4 
 5     public T2(Phone phone) {
 6         this.phone = phone;
 7     }
 8 
 9     public void installApk() {
10         System.out.println("可以安装Android软件了");
11     }
12 
13     @Override
14     public void tel() {
15         phone.tel();
16     }
17 
18     @Override
19     public void sms() {
20         phone.tel();
21     }
22 
23 }
复制代码

T3类设计与之类似,那么现在T2需要支持电信用户呢?这是直接修改T2类即可,并且对其他类(因为它没有子类之说了)是没有影响的。

复制代码
 1 class T2 implements Phone {
 2 
 3     private Phone phone;
 4 
 5     public T2(Phone phone) {
 6         this.phone = phone;
 7     }
 8 
 9     public void installApk() {
10         System.out.println("可以安装Android软件了");
11     }
12 
13     @Override
14     public void tel() {
15         this.supportDx();
16         phone.tel();
17     }
18 
19     @Override
20     public void sms() {
21         this.supportDx();
22         phone.tel();
23     }
24 
25     public void supportDx() {
26         System.out.println("可以支持电信用户了");
27     }
28 
29 }
复制代码

测试:

复制代码
 1 public class DecoratorTest {
 2 
 3     public static void main(String[] args) {
 4         Phone t1 = new T1();
 5         Phone t2 = new T2(t1);
 6         t2.tel();
 7         t2.sms();
 8     }
 9 
10 }
复制代码

怎么样,利用装饰模式设计类代替原本的继承是不是优势马上显示出来了,可能有人会说,这样设计会违背T2的愿意,可能有些T2本没必要支持电信用户,哦,确实如此,那好办啊,在创建的时候T2对象的时候加一个参数去控制就可以了啊。大概如下:

复制代码
 1 class T2 implements Phone {
 2 
 3     private Phone phone;
 4     private boolean isSupportDx;
 5 
 6     public T2(Phone phone, boolean isSupportDx) {
 7         this.phone = phone;
 8         this.isSupportDx = isSupportDx;
 9     }
10 
11     public void installApk() {
12         System.out.println("可以安装Android软件了");
13     }
14 
15     @Override
16     public void tel() {
17         this.supportDx();
18         phone.tel();
19     }
20 
21     @Override
22     public void sms() {
23         this.supportDx();
24         phone.tel();
25     }
26 
27     public void supportDx() {
28         if (isSupportDx) {
29             System.out.println("可以支持电信用户了");
30         }
31     }
32 
33 }
复制代码
复制代码
 1 public class DecoratorTest {
 2 
 3     public static void main(String[] args) {
 4         Phone t1 = new T1();
 5         Phone t2 = new T2(t1, true); // Phone t2 = new T2(t1, false);
 6         t2.tel();
 7         t2.sms();
 8     }
 9 
10 }
复制代码

 怎么样?装饰模式还是不错的吧,Java IO中的包装流都是采用装饰模式实现的哦。。

 

---------------------------------------------------------------------------------
笔者水平有限,若有错漏,欢迎指正,如果转载以及CV操作,请务必注明出处,谢谢!
分类: 设计模式

本文转自Windstep博客园博客,原文链接:http://www.cnblogs.com/lwbqqyumidi/p/3750634.html,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
设计模式 存储 缓存
聊聊Java设计模式-装饰器模式
装饰器模式允许向一个现有的对象添加新的功能,同时不改变其结果。比如Java 中的IO框架中,`FileInputStream`(处理文件)、`ByteArrayInputStream`(处理字节数组)、`BufferedInputStream`(带缓存的处理类)等就是对`InputStream`进行的功能扩展,这就是装饰器模式的典型应用。
38 1
聊聊Java设计模式-装饰器模式
|
2月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
39 1
|
24天前
|
设计模式 Java
Java设计模式:深入装饰器模式的三种写法(六)
Java设计模式:深入装饰器模式的三种写法(六)
|
2月前
|
设计模式
设计模式之装饰器 Decorator
设计模式之装饰器 Decorator
30 1
|
1月前
|
设计模式 架构师 安全
设计模式第五讲-装饰器模式和代理模式详解
远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
189 0
|
2月前
|
设计模式 传感器 数据处理
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
装饰器模式是一种设计模式,它允许在运行时向对象添加额外的职责,而无需修改其代码。这种模式提供了一种动态扩展对象功能的方法,同时保持了对象的单一职责原则。本文介绍了装饰器模式的基本概念、原理、优势、适用场景、实现方法、最佳实践和注意事项。通过装饰器模式,可以将多个行为组合成一个更复杂的行为,而无需使用继承或大量的接口实现。装饰器模式适用于需要对一个对象进行一系列的增强处理的情况,而这些增强处理可以以一种松耦合的方式进行组合。通过使用装饰器模式,可以提高代码的可维护性、可扩展性和灵活性,使系统更加灵活和易于维护
69 1
探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀
|
2月前
|
设计模式 缓存 监控
设计模式之装饰器模式
**装饰器模式**是一种设计模式,用于在运行时动态添加或移除对象的功能,保持接口不变,无需修改原始代码。它适用于不修改已有代码而需动态扩展功能的场景。常见应用包括GUI组件增强、Web开发中的函数扩展、缓存与代理、日志记录、数据库连接池和事务管理等。在Java的Web开发中,Spring框架的拦截器(Interceptor)是一个实现示例,用于权限控制等预处理或后处理任务。
|
2月前
|
设计模式 Java
23种设计模式,装饰器模式的概念优缺点以及JAVA代码举例
【4月更文挑战第5天】装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。
51 6
|
2月前
|
设计模式 Java
设计模式之装饰器模式
设计模式之装饰器模式
|
2月前
|
设计模式
装饰器模式--设计模式
装饰器模式--设计模式
23 0