2012-04-02 163 views

回答

24

的主要區別:

  • 類適配器使用繼承,只能緊裹。它不能包裝一個接口,因爲根據定義它必須來自某個基類。

  • 對象適配器使用組合物和可以包裝類或接口,或兩者。它可以這樣做,因爲它包含作爲私有封裝成員的類或接口對象實例它包裝。

區別是微妙的。通常(有利於composition over inheritance)的後一種方法是優選的,因爲在我將在這裏引用的鏈接解釋說:

爲 重用的功能面向對象編程(OOP)已經太出名的候選人:繼承(白盒重用)和合成 (黑盒重用)。如果您嘗試通過從類 中獲取來重用代碼,您將使子類依賴於父類。這使得在許多情況下系統不必要地複雜,不易測試,並且使得在運行時功能的交換不必要地困難。作爲[Clean Code Developer] 當您需要決定繼承是否合適時,您應該遵循Liskov Substitution Principle (LSP)

構圖意味着一個班級使用另一個班級。您將通過明確定義界面來進一步促進解耦。這也將 給你的優勢,實現可以很容易地取代。所以 在開始應用Liskov替換原理之前,請考慮 關於繼承概念的構成組合,並要求 您還有12個爲什麼不應該立即選擇構圖。

「由於繼承公開其子類的細節,其父實現的細節,它通常被稱爲'繼承打破 封裝'」。(四1995年剛:19)

4

對象適配器:

$Adapter = new MyEngine(new MyAdapter($options)); 
$Adapter->write('something'); 

類適配器

MyAdapter extends BaseAdapter implements AdapterInterface { ... } 
$Adapter = new MyAdapter($options); 
$Adapter->write('something'); 
1

類適配器使用多重繼承到一個接口適應另:(取決於你的編程語言:Java的& C#不支持多重繼承)

enter image description here

對象適配器取決於對象組成:

enter image description here

像S烏爾斯河:設計模式(可複用面向對象軟件的元素)一書

4

簡單的話, 類適配器使用子類和對象適配器用組合物使用授權。

實施例:

class MyExistingServiceClass { 
    public void show() { 
     System.out.println("Inside Service method show()");   
    } 
} 

interface ClientInterface { 
    void display(); 
} 

class MyNewClassAdapter extends MyExistingServiceClass implements ClientInterface { 
    void display() { 
     show(); 
    } 
} 

以上是類適配器的一個例子。我們通過從display()的實現中調用現有的show()方法,將MyExistingServiceClass調整爲ClientInterface。

爲了將它轉換爲對象適配器,該代碼將是這樣的:

class MyNewObjectAdapter implements ClientInterface { 

    MyExistingServiceClass existingClassObject; 

    void display() { 
     existingClassObject.show(); 
    } 
} 

現在,當到位類Adatper的使用對象適配器,

  1. 當沒有辦法繼承該類將根據客戶端界面進行調整。例如,當MyExistingServiceClass被聲明爲final時。

  2. 當客戶端期望一個不是inteface而是一個抽象類實現的合同。在這種情況下,我們沒有別的辦法,只能繼承客戶的期望類,因爲我們不能爲一個以上的類繼承類,所以除了使用類作爲組合之外別無他法。

    abstract class AbstractClientClass { 
        abstract void display(); 
    } 
    
    class MyNewObjectAdapter extends AbstractClientClass { 
    
        MyExistingServiceClass existingClassObject; 
    
        void display() { 
         existingClassObject.show(); 
        } 
    } 
    
  3. 當您需要修改多個對象時。這種情況是當你沒有直接使用被修改的對象時。這裏的一個好例子是javax.swing中的JTable類。此類創建一個GUI(圖形用戶界面)表格組件,其中填充了適配器向其提供的信息。要顯示來自域的數據,JTable提供的構造函數接受javax.swing.table中定義的TableModel 的實例。 JDK使用AbstractTableModel提供了現有的TableModel抽象實現。

    class MyTableModel extends AbstractTableModel { 
    
    MyDomainObject[] existingDomainObjects[]; 
    
    public int getColumnCount() { 
        return 4; 
    } 
    
    public int getRowCount() { 
        return existingDomainObjects.length(); 
    } 
    
    public MyDomainObject getValueAt(int i) { 
        return existingDomainObjects[i]; 
    } 
    } 
    

在這裏,我們已經適應MyDomainObject爲了與AbstractTableModel上使用。