裝飾模式(Decorator)

  裝飾模式(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是能夠省略的:

        

相關文章
相關標籤/搜索