装饰器设计模式初探及Java中实际应用举例
本篇随笔主要介绍用Java实现简单的装饰器设计模式:
先来看一下装饰器设计模式的类图:
从图中可以看到,我们可以装饰Component接口的任何实现类,而这些实现类也包括了装饰器本身,装饰器本身也可以再被装饰。
下面是用Java实现的简单的装饰器设计模式,提供的是从基本的加入咖啡入手,可以继续加入牛奶,巧克力,糖的装饰器系统。
1 interface Component { 2 void method(); 3 } 4 class Coffee implements Component { 5 6 @Override 7 public void method() { 8 // TODO Auto-generated method stub 9 System.out.println("倒入咖啡"); 10 } 11 12 } 13 class Decorator implements Component { 14 public Component comp; 15 public Decorator(Component comp) { 16 this.comp = comp; 17 } 18 @Override 19 public void method() { 20 // TODO Auto-generated method stub 21 comp.method(); 22 } 23 24 } 25 class ConcreteDecorateA extends Decorator { 26 public Component comp; 27 public ConcreteDecorateA(Component comp) { 28 super(comp); 29 this.comp = comp; 30 } 31 public void method1() { 32 System.out.println("倒入牛奶"); 33 } 34 public void method2() { 35 System.out.println("加入糖 "); 36 } 37 public void method() { 38 super.method(); 39 method1(); 40 method2(); 41 } 42 } 43 class ConcreteDecorateB extends Decorator { 44 public Component comp; 45 public ConcreteDecorateB(Component comp) { 46 super(comp); 47 this.comp = comp; 48 } 49 public void method1() { 50 System.out.println("加入巧克力"); 51 } 52 public void method() { 53 super.method(); 54 method1(); 55 } 56 } 57 public class TestDecoratePattern { 58 public static void main(String[] args) { 59 Component comp = new Coffee(); 60 comp.method(); 61 System.out.println("--------------------------------------------------"); 62 Component comp1 = new ConcreteDecorateA(comp); 63 comp1.method(); 64 System.out.println("--------------------------------------------------"); 65 Component comp2 = new ConcreteDecorateB(comp1); 66 comp2.method(); 67 System.out.println("--------------------------------------------------"); 68 Component comp3 = new ConcreteDecorateB(new ConcreteDecorateA(new Coffee())); 69 comp3.method(); 70 System.out.println("--------------------------------------------------"); 71 Component comp4 = new ConcreteDecorateA(new ConcreteDecorateB(new Coffee())); 72 comp4.method(); 73 } 74 }
运行结果:
装饰器设计模式可以使得我们自由的,以任意顺序导入巧克力,牛奶,咖啡和糖。可以实现多层,任意顺序的装饰。
Java中实际应用举例:
1、java io流
以下一句代码即体现了装饰器设计模式的应用:
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(new File(filePath), true)));
PrintWriter类及BufferedWriter类就相当于上面装饰器设计模式类图中的ConcreteDecorateA 与 ConcreteDecorateB,FileWriter类则相当于上面类图中的ConcreteComponent类,PrintWriter类的构造器实际接受的是一个Writer类的对象,在这里即为BufferedWriter类的对象,然后对这个Writer类的write方法进行装饰。
2、web应用中在filter类中实现自定义的输入输出
filter类实现如下:
public class AllFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //自定义输出流 ServletResponse compressionResponse = new CompressionResponseWrapper((HttpServletResponse) servletResponse); //把自定义的输出流传递到用户实现的servlet中去 filterChain.doFilter(servletRequest, compressionResponse); } @Override public void destroy() { } }
其中自定义的输出流 CompressionResponseWrapper 类就是装饰器设计模式的一个应用。CompressionResponseWrapper类实现如下:
public class CompressionResponseWrapper extends HttpServletResponseWrapper { private HttpServletResponse response; public CompressionResponseWrapper(HttpServletResponse response) { super(response); this.response = response; } @Override public ServletOutputStream getOutputStream() throws IOException { System.out.println("在这里可对输出流进行定制操作,例如进行压缩,返回压缩后的新的输出流"); return response.getOutputStream();
}
}
这里CompressionResponseWrapper类相当于上述装饰器设计模式类图中的ConcreteDecorateA类,HttpServletResponse类则相当于待装饰的接口。CompressionResponseWrapper类还可以再被装饰添加其他功能,这就是装饰器设计模式的强大之处。