本篇隨筆主要介紹用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類還可以再被裝飾添加其他功能,這就是裝飾器設計模式的強大之處。
