裝飾模式(Decorator)最多見的就是JDK中的關於I/O流的處理。java
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));編程
裝飾模式的類圖以下:測試
首先是抽象的接口Componentthis
public interface Component{ void sampleOperation(); }
下面是裝飾角色的代碼Decorator,繼承了Component接口,調用的方法仍是父類的方法,但並非單純的調用父類方法,而是在功能上有所加強。 spa
public class Decorator implements Component{ private Component component; public Decorator(Component component){ this.component = component; } public Decorator() {
//write code here } public void sampleOperation(){ component.sampleOperation(); } }
具體裝飾角色的源代碼以下,3d
public class ConcreteDecorator extends Decorator{ public void sampleOperation(){ super.sampleOperation(); } }
一個典型的裝飾模式的建立過程以下: code
new Decorator1(new Decorator2(new Decorator(new ConcreteComponent())))
Decorator1持有一個Decorator2對象的引用,後者持有一個Decorator3的引用,Decorator3持有的是ConcreteDecorator的引用。component
齊天大聖的例子中,齊天大聖角色是抽象接口Component,ConcreteComponent是大聖本尊,就是本人。大聖化身是Decorator角色,而花,鳥,魚,蟲的角色是ConcreteDecorator。對象
齊天大聖的示例代碼: blog
public interface MonkeyKing{ public void laugh(); }
大聖本尊的實例代碼:
public class MonkeySelf implements MonkeyKing{ public MonkeySelf (){ } public void laugh(){ System.out.println("laugh like a monkey!"); } }
大聖化身的實例代碼:
public class MokeyAvactor implements MonkeyKing{ private MonkeyKing mk; public MokeyAvactor(MonkeyKing mk){ this.mk = mk; } public void laugh(){ mk.laugh(); } }
大聖變成的魚的實例代碼:
public class FishAvator extends MokeyAvactor{ public FishAvator(MonkeyKing mk){ super(mk); } public void laugh(){ super.laugh(); } public void swim(){ System.out.println("FishAvator is swimming!"); } }
大聖變成的鳥的實例代碼:
public class BirdAvator extends MokeyAvactor{ public BirdAvator(MonkeyKing mk){ super(mk); } public void laugh(){ super.laugh(); } public void fly(){ System.out.println("BirdAvator is flying!"); } }
測試各類變身的類的代碼:
public class AvatorTest { public static void main(String [] args){ MonkeyKing mk = new MonkeySelf(); MonkeyKing fish = new FishAvator(mk); fish.laugh(); MonkeyKing bird = new BirdAvator(fish); bird.laugh(); } }
測試的結果爲:
laugh like a monkey!
laugh like a monkey!
由大聖本尊化身爲的鳥和魚的laugh調用的仍是大聖本尊的laugh。
MonkeyKing fish = new FishAvator(mk);符合面向接口編程的原則,可是若是須要用Fish的swim方法,這種寫法就不行了,只能寫成:
FishAvator fish = new FishAvator(mk);這種被稱爲半透明的裝飾模式,或者稱爲退化的裝飾模式。
裝飾模式提供了比繼承更爲靈活的功能,經過不一樣的組合,對象將擁有不一樣的屬性。
回到最開始的I/O流中的代碼:
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("test.txt")));
查看代碼,DataInputStream中的read方法都是調用傳入的InputStream的read方法,對應上面就是調用的BufferedInputStream的read方法。
InputStream能夠看作抽象接口,BufferedInputStream能夠看作ConcreteComponent,DataInputStream能夠看作ConcreteDecorator,就能夠和上面裝飾模式的類圖對應上了。
實際中使用的裝飾模式要比剛開始的類圖結構簡單些,下面是簡化了的裝飾模式的類圖。
省略Component的狀況:
只有一個ConcreteDecorator,則Decorator是能夠省略的: