1.产生背景
- 为什么需要装饰器模式
某些情况,当一个类已经存在,并且可以对外提供核心功能时,但是,某个时刻,希望对这个类进行功能增强(如:增加缓存);通常情况,我们可以修改原来的类,并增加对应的增强功能即可;
但是,这种方式违背了“开-闭”原则,需要修改原来的代码;而且不够灵活,如果有某个时刻又不想使用缓存,又需要修改原来的代码,显然,这不是一个很好的解决方案;
2.概念
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。
本质: 引入一个中介类,这个类实现了被装饰者相同的接口,对外假装成被装饰者,并通过引用被装饰者,在调用被装饰者前后做一些附加功能(如:缓存,参数预处理);
3.目的
不修改原来代码的情况下,动态地给一个对象添加一些额外的职责和功能
本质:动态增加功能;把需要新增加的功能预先制作成零件,在需要时“动态“的添加到对象上;
装饰器模式相比生成子类更为灵活
4.解决方案
本质:引入一个第三方中介类,这个类实现了被装饰类的接口,并引用了被装饰对象,对外假装成被装饰对象,对内通过调用被装饰对象完成最终功能,在调用被装饰对象之前之后,可以做一些额外的功能(这也是装饰模式功能增强的地方);
- 引入中介对象
- 中介对象实现被装饰类的接口(对外假装成被装饰类)
- 中介对象内部引用被装饰类(并把真实功能委托给被装饰对象);
- 中介对象在调用被装饰对象前后:增加特殊功能
5. 类图
6.优缺点
优点:
松耦合
在不修改原来代码的情况下,动态的为原类增加新功能扩展性高
只需要增加新的装饰类,就可以对原类不断增加新功能- 灵活
不需要通过继承来扩展,而且可以动态增加或去除新装饰类,从而随意对原对象增加或减少某些功能
最核心的目的:在不修改原代码的情况下,动态的为对象增加或减少某些功能
缺点:
- 额外引入第三方
7.应用场景
- 扩展类的功能时
- 动态增加或取消某些功能时
“与代理模式的区别”
在学习装饰器模式时,会发现它与代理模式无论从实现结构,还是功能目的都非常接近;
装饰器模式侧重的是对功能的增强,不改变原功能;
装饰器模式使用方明确知道自己需要什么的增强功能,硬编码使用;
代理模式侧重于对原功能的改变(特别是访问权限的控制)
代理模式分为静态和动态代理,动态代理是在调用方不知情的情况下使用;
如果代理模式使用静态代理实现,而且也是侧重对功能的增强,那么他们之间没有任何区别(如:spring中通过动态代理实现缓存或日志)
因此:代理在java中,更多的应用在动态AOP上;
8.现实案例
JDK中的流处理;
ByteArrayInputStream
FileInputStream
ObjectInputStream
PipedInputStream