一、什麼是裝飾模式 通過關聯機制給類增加行為,其行為的擴展由修飾對象來決定; 如JAVA IO流里的以下形式,BufferedReader為裝飾類,其關聯了一個具體對象(new FileReader(new File("test.txt"))),並對其進行裝飾,裝飾後擁有readLine行為(方法)
一、什麼是裝飾模式
通過關聯機制給類增加行為,其行為的擴展由修飾對象來決定;
如JAVA IO流里的以下形式,BufferedReader為裝飾類,其關聯了一個具體對象(new FileReader(new File("test.txt"))),並對其進行裝飾,裝飾後擁有readLine行為(方法):
new BufferedReader(new FileReader(new File("test.txt")));
二、補充說明
與繼承相似,不同點在於繼承是在編譯期間擴展父類,而裝飾器模式在運行期間動態擴展原有對象;
或者說,繼承是對類進行擴展,裝飾模式是對對象進行擴展;
三、角色
抽象構件
具體構件
抽象裝飾類
具體裝飾類
說明:具體構件、抽象裝飾類、具體裝飾類的共同父類是抽象構件,具體裝飾類繼承抽象裝飾類併在運行期間裝飾具體構件;
四、例子
例子說明:
畫家介面Painter,為抽象構件,有兩個方法,獲取畫家描述信息及繪畫;
PaintBeginner實現Painter介面,為具體構件;
PainterDecorator實現Painter介面,為抽象裝飾類,其內部關聯一個Painter對象,通過構造函數獲取;
HillPainterDecorator、RiverPainterDecorator、TreePainterDecorator為具體裝飾類,表明被裝飾的畫家能夠繪畫Hill、River、Tree;
類圖:
代碼實現:
Painter.java
package com.pichen.dp.decorator; public interface Painter { public abstract String getDescription(); public abstract String painting(); }View Code
PaintBeginner.java
package com.pichen.dp.decorator; public class PaintBeginner implements Painter{ @Override public String getDescription() { return ""; } @Override public String painting() { /* do nothing */ return ""; } }View Code
PainterDecorator.java
package com.pichen.dp.decorator; public abstract class PainterDecorator implements Painter{ private Painter decoratedPainter; public PainterDecorator(Painter decoratedPainter) { this.decoratedPainter = decoratedPainter; } public Painter getPainter(){ return this.decoratedPainter; } }View Code
HillPainterDecorator.java
package com.pichen.dp.decorator; public class HillPainterDecorator extends PainterDecorator{ public HillPainterDecorator(Painter paper) { super(paper); } @Override public String getDescription() { return this.getPainter().getDescription() + "can paint hill, "; } @Override public String painting() { /* painting the hill */ return this.getPainter().painting() + paintingHill(); } public String paintingHill(){ return "Hill, "; } }View Code
RiverPainterDecorator.java
package com.pichen.dp.decorator; public class RiverPainterDecorator extends PainterDecorator{ public RiverPainterDecorator(Painter paper) { super(paper); } @Override public String getDescription() { return this.getPainter().getDescription() + "can paint river, "; } @Override public String painting() { /* painting the river */ return this.getPainter().painting() + paintingRiver(); } public String paintingRiver(){ return "River, "; } }View Code
TreePainterDecorator.java
package com.pichen.dp.decorator; public class TreePainterDecorator extends PainterDecorator{ public TreePainterDecorator(Painter paper) { super(paper); } @Override public String getDescription() { return this.getPainter().getDescription() + "can paint tree, "; } @Override public String painting() { /* painting the tree */ return this.getPainter().painting() + paintingTree(); } public String paintingTree(){ return "Tree, "; } }View Code
Main.java
package com.pichen.dp.decorator; public class Main { public static void main(String[] args) { Painter p0 = new PaintBeginner(); System.out.println("Painter description:" + p0.getDescription()); System.out.println("Painting:" + p0.painting() + "\n"); HillPainterDecorator p2 = new HillPainterDecorator(new PaintBeginner()); System.out.println("Painter description:" + p2.getDescription()); System.out.println("Painting:" + p2.painting()); System.out.println("Painting:" + p2.paintingHill() + "\n"); //新增的行為 RiverPainterDecorator p3 = new RiverPainterDecorator(new PaintBeginner()); System.out.println("Painter description:" + p3.getDescription()); System.out.println("Painting:" + p3.painting()); System.out.println("Painting:" + p3.paintingRiver() + "\n"); //新增的行為 HillPainterDecorator p4 = new HillPainterDecorator(new RiverPainterDecorator(new TreePainterDecorator(new PaintBeginner()))); System.out.println("Painter description:" + p4.getDescription()); System.out.println("Painting:" + p4.painting()); System.out.println("Painting:" + p4.paintingHill() + "\n"); //新增的行為 } }
執行結果如下,PaintBeginner類的對象未裝飾前,無行為;在被裝飾器裝飾後,行為可以改變:
五、JAVA IO流與裝飾模式
這裡簡單的以Reader、BufferedReader、FileReader舉個例子,如下代碼:
BufferedReader br = new BufferedReader(new FileReader(new File("test.txt"))); br.readLine();
說明:
其中BufferedReader與FileReader有一個共同抽象父類Reader,Reader為抽象構件;
new FileReader(new File("test.txt"))為具體構件,運行期間被修飾的對象;
BufferedReader為具體修飾類,運行期間修飾具體構件;
裝飾後,被修飾的對象新增的行為是擁有readLine方法;
ps:查看源碼,沒發現BufferedReader對應的抽象裝飾類,個人覺得沒有抽象裝飾類,裝飾模式也是可以正常工作的,抽象構件(Reader)可以由具體修飾類關聯;
另外,具體修飾類也可以作為基類,被其它類繼承的,繼承後的類同樣也是具體修飾類,如LineNumberReader就是繼承BufferedReader;
所以,上面語句還可以這樣寫(ps:只是舉例,其實沒必要用BufferedReader修飾,直接LineNumberReader裝飾下就可以):
BufferedReader br = new LineNumberReader(new BufferedReader(new FileReader(new File("test.txt")))); br.readLine();