1. 程式人生 > >java設計模式4.介面卡模式、裝飾器模式

java設計模式4.介面卡模式、裝飾器模式

  • 介面卡模式

把一個類的介面變換成客戶端所期待的另一種介面,從而使原本因介面不匹配而無法在一起工作的兩個類能夠工作。

1. 類的介面卡模式

  • 目標角色:期望的介面,對於類的介面卡模式,此角色不可以是具體類。
  • 源角色:需要適配的介面。
  • 介面卡角色:把源介面轉換成目標介面,此角色必須是具體類。
public interface Target {
    
    void fun2();
}
public class Adaptee {
    
    public void fun1(){
        
    }
}
// 介面卡Adapter擴充套件了Adaptee,同時也實現了介面Target。這樣Adapter的型別是Adaptee同時也提供Target要求的方法。
public class Adapter extends Adaptee implements Target { @Override public void fun2() { // TODO Auto-generated method stub } }

2. 物件的介面卡模式

  • 目標角色:期望的介面,可以是具體或抽象的類。
  • 源角色: 需要適配的介面。
  • 介面卡角色:把源介面轉換成目標介面,此角色必須是具體類。
public class Adapter implements Target {
    
    
private Adaptee adaptee; public Adapter(Adaptee adaptee){ this.adaptee = adaptee; } public void fun1(){ adaptee.fun1(); } @Override public void fun2() { // TODO Auto-generated method stub } }

可以看出,物件介面卡與類介面卡的區別是使用物件組合代替了型別繼承。這樣一個介面卡可以把多種不同的源介面卡到同一個目標。但與類介面卡相比,要想置換源類的方法就不太容易,如果一定要置換,可以先做好一個源類的子類置換掉方法,然後將子類當作真正的源進行適配。不過要是想增加一些新的方法則很方便,而且新增加的方法可以同時適用於所有的源。

  • 裝飾器模式

裝飾模式以對客戶端透明的方式擴充套件物件的功能,是繼承關係的一個替代方案。使用原來被裝飾的類的一個子類的例項,把客戶端的呼叫委派到被裝飾類。

  • 抽象構建角色:給出一個抽象介面,以規範準備接收附加責任的物件。
  • 具體構建角色:定義一個將要接收附加責任的類。
  • 裝飾角色:持有一個構建物件的例項,並定義一個與抽象構建介面一致的介面。
  • 具體裝飾角色:負責給構建物件貼上附加的責任。

具體裝飾角色實現了構建介面,對於每一個實現的方法都委派給父類的構建角色,關鍵在於它功能的增強,而不是單純地委派。

  • 示例:IO設計

java api的io類庫中對於介面卡裝飾器的應用隨處可見,這裡以讀取檔案為例,看一下其中的相關的幾個類。

// 讀取一個檔案內容
BufferedReader in = new BufferedReader(new FileReader(new File("test.txt")));

BufferedReader是一個典型的裝飾器模式,它實現了Reader介面,同時也擁有Reader子類的一個例項,這裡也就是FileReader,然後將所有的讀取任務都委託給了FileReader的例項,但是增加了快取讀取功能。

我們通常會說InputStreamReader是從byte輸入流到char輸入流的一個介面卡,但其實起到介面卡作用的是StreamDecoder,它擁有InputStream的例項同時實現了Reader介面,而InputStreamReader在此基礎上進一步裝飾了StreamDecoder。

說一個讓java初學者糾結的一個問題,io流關閉問題:由於使用的裝飾器模式,對於io流的close,我們只要呼叫最外層的close方法就可以了。比如BufferedReader會將close的操作委託給reader例項,這個例項正常是InputStreamReader的實現,然後InputStreamReader又委託給StreamDecoder,最後StreamDecoder又會委託給InputStream的實現類,最終實現了IO流關閉,反過來如果提前呼叫了委託類的close方法,那麼上層的讀取也會失敗。

#筆記內容參考《java與模式》