1、概念
装饰器模式是在不修改原类的情况下,通过添加新的装饰器类,对原有功能进行扩展。
它的主要应用场景是同一对象从不同角度去归类时,需要不同的功能和处理方式,而对象的具体类型是运行阶段时决定的。
装饰器模式的类结构不复杂,但是代码实现会很复杂,因为它基于对原始类的认知。
原始类的认知可以抽象为三个方面:
1. 划分的角度
2. 基于划分角度的对象归类
3. 不同种类的功能,以及处理方式
例如HttpRequest对象,从响应的内容可以分为静态资源请求时,数据请求。从请求的数据类型可以划分为二进制流请求,其他数据类型请求(大部分为字符串)。从请求方式的角度,可以划分为GET,POST,PUT,DELETE等请求。依据不同的请求类型,它们的处理方式也是不同的。
2、UML图
3、代码
XXInterface,被装饰的接口类
/** * * @File Name: SomeInterface.java * @Description: 某个被装饰的接口, 如果是Web应用时,可以理解它扮演着ServletRequest或者是HttpServletRequest的作用 * @version 1.0 * @since JDK 1.8 */ public interface SomeInterface { // 实现某个功能 void func(); }
XXInterfaceImpl,被装饰的接口实现类
/** * * @File Name: SomeInterfaceImpl.java * @Description: 具体的实现类,对应ServletRequestWrapper * @version 1.0 * @since JDK 1.8 */ public class SomeInterfaceImpl implements SomeInterface{ @Override public void func() { } }
SomeDecoratorInterface,扮演者装饰器接口的角色,通常提供附加的功能
/** * * @File Name: SomeDecoratorInterface.java * @Description: 装饰器接口,当为 * @version 1.0 * @since JDK 1.8 */ public interface SomeDecoratorInterface extends SomeInterface { // 例如针对MultiPart附加的一些额外方法,当没有附加功能时,此接口可以不存在 // 例如在Servlet中,ServletRequestWrapper直接实现ServletRequest接口,就没有与这个类相同职责的接口 void addtionalFunc(); }
SomeDecorateImpl,扮演者装饰器类的角色,若只想修改功能的实现方式,它可以实现被装饰的接口,此时装饰器接口没有存在的意义。
/** * * @File Name: SomeDecorateImpl.java * @Description: 装饰器接口实现类,扮演着装饰器类的角色。这里它主要的职责是附加了额外的功能,addtionalFunc * 例如常见的缓存功能。 * @version 1.0 * @since JDK 1.8 */ public class SomeDecorateImpl implements SomeDecoratorInterface { // 被装饰的原始类,在Web中相当于ServletRequest或HttpServletRequest private SomeInterface someInterface; public SomeDecorateImpl(SomeInterface someInterface) { this.someInterface = someInterface; } @Override public void func() { someInterface.func(); } @Override public void addtionalFunc() { // 额外功能的具体实现 } }
个人建议去分析MultiPartRequest与ServletRequest的
4、讨论
问题1:装饰器模式的主要功能是?
答:在不修改原类的基础上添加附加的功能,或者修改已有功能的实现方式。
问题2:对装饰器模式的一些理解
答:装饰器模式的类结构不是很复杂,但是它很难,因为要达到全面认识原始类很难。
装饰器模式的”装饰”是不限制层次的,所以装饰器类是可以再次被装饰的,但是不建议这样,因为会导致类结构变的很复杂。
装饰器模式中被装饰的类或对象最好是顶层类或顶层接口,附加的功能最好是提供额外的接口进行继承,并提供默认的抽象类实现此接口,这样新增的装饰器类只需要继承抽象类,实现附加功能即可。
5、示例
1. Servlet或HttpServlet的类结构体系。
2. IO中inputStream和OutputStream的类结构体系。