装饰模式(Decorator)
定义:对象的一种结构模式
能够动态的为一个对象添加一些额外的行为职责
继承也可以实现上述功能,但是这是一个编译器的扩展而不是运行期的扩展模式.装饰模式正是为了解决“过渡依赖使用继承来进行对象的的功能扩展”而时设的
目的:进行对象行为职责扩展
特性:动态(扩展特性在运行期自动获得)
这是装饰模式的基本实现中所涉及的角色:
原始接口(Component):定义了一个接口方法
默认目标实现类(TargetComponent):对于原始接口的默认实现方式。在装饰模式中,默认目标实现类被认为是有待扩展的类,器方法operation被认为是有待扩展的行为方法。
装饰实现类(ComponentDecorator):同样实现了原始接口,既可以是一个抽象类,也可以是一个具体实现类。其内部封装了一个原始接口的对象实例:targetComponent,这个实例的实现往往被初始化成默认目标实现类(TargetComponent)
具体装饰实现类(ComponentDecoratorA,ComponentDecoratorB):集成子装饰类,我们可以在operations方法中调用原始接口的对象实例targetComponent获得默认目标实现类的行为方式并在其中加入行为扩展实现,也可以自由添加新的行为addBehaviorA等。
装饰模式的构成要素:
默认目标实现(TargetComponent)类封装于具体的装饰实现类(ComponentDecorator)或者其子类的内部,从而形成对象之间的引用关系
具体装饰实现类(ComponentDecorator)同样实现了原始接口(Component)
例如:servlet标准接口设计中,天然包含了对HttpServletRequest和HttpServletResponse这两大接口的装饰实现类
HttpServletRequest和HttpServletResponse是Servlet标准所指定的Java语言与Web容器进行交互的接口,接口本身只规定Java语言对web容器进行访问的行为方式,而具体的实现是由不同的web容器在其内部实现的。例如,Tomcat Weblogic或者Websphere等不同的web容器对HttpServletRequest和HttpServletResponse的实现解释不同。
那么在运行期间,当我们需要对HttpServletRequest或HttpServletResponse的默认客观实现行为进行扩展时我们就可以继承HttpServletRequestWrapper或者HttpServletResponseWrapper来实现。事实上,无论是HttpServletRequestWrapper和HttpServletResponseWrapper,他们都提供了一个可传入对应HttpServletRequest和HttpServletResponse接口的构造函数,并在构造函数中实现了将原始HttpServletRequest和HttpServletResponse接口的实现封装于内部的基本逻辑。
装饰模式作为对象行为的扩展方式比继承更合理的地方:虽然装饰模式产生的初衷是装饰类对默认目标实现类的行为扩展,然而装饰类却并不对默认目标实现类形成依赖。
package com.slp.Decorator; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; public class SampleRequestWrapper extends HttpServletRequestWrapper { private CacheManager cacheManager; public SampleRequestWrapper(HttpServletRequest request) { super(request); // TODO Auto-generated constructor stub } /** * 根据key值 首先在cache中查找,再调用基类方法查找 */ public Object getAttribute(String s) { if (s != null && s.startsWith("cacheable")) { String cacheKey = s.substring("cacheable.".length()); return cacheManager.getValue(cacheKey); } else { return super.getAttribute(s); } } }
有了这个类之后,我们就可以在处理URL请求的Filter中将原始的HttpServletRequest替换成这个装饰实现类。
package com.slp.Decorator; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; public class SampleFilter { public void doFilter(ServletRequest req,ServletResponse res,FilterChain chain) throws IOException, ServletException{ HttpServletRequest request=(HttpServletRequest)req; request=new SampleRequestWrapper(request); chain.doFilter(request, res); } }
这样的话,我们就在整个Request生命周期获得了HttpServletRequest的扩展:因为对于HttpServletRequest来说,其原生的getAttribute方法的行为被加入了从缓存中读取数据的新特性。
这也实现了对默认目标实现进行选择性扩展