如何決定何時使用對象適配器以及何時使用類適配器?對象適配器模式和類適配器模式之間的區別
問題說明: 要創建社交網站並提供來自Facebook,Google Plus和orkut的導入功能。我無法決定是使用對象適配器還是類適配器。
我曾看過Adapter Pattern: Class Adapter vs Object Adapter,但無法理解差異的本質。
如何決定何時使用對象適配器以及何時使用類適配器?對象適配器模式和類適配器模式之間的區別
問題說明: 要創建社交網站並提供來自Facebook,Google Plus和orkut的導入功能。我無法決定是使用對象適配器還是類適配器。
我曾看過Adapter Pattern: Class Adapter vs Object Adapter,但無法理解差異的本質。
的主要區別:
類適配器使用繼承,只能緊裹類。它不能包裝一個接口,因爲根據定義它必須來自某個基類。
對象適配器使用組合物和可以包裝類或接口,或兩者。它可以這樣做,因爲它包含作爲私有封裝成員的類或接口對象實例它包裝。
區別是微妙的。通常(有利於composition over inheritance)的後一種方法是優選的,因爲在我將在這裏引用的鏈接解釋說:
爲 重用的功能面向對象編程(OOP)已經太出名的候選人:繼承(白盒重用)和合成 (黑盒重用)。如果您嘗試通過從類 中獲取來重用代碼,您將使子類依賴於父類。這使得在許多情況下系統不必要地複雜,不易測試,並且使得在運行時功能的交換不必要地困難。作爲[Clean Code Developer] 當您需要決定繼承是否合適時,您應該遵循Liskov Substitution Principle (LSP)。
構圖意味着一個班級使用另一個班級。您將通過明確定義界面來進一步促進解耦。這也將 給你的優勢,實現可以很容易地取代。所以 在開始應用Liskov替換原理之前,請考慮 關於繼承概念的構成組合,並要求 您還有12個爲什麼不應該立即選擇構圖。
「由於繼承公開其子類的細節,其父實現的細節,它通常被稱爲'繼承打破 封裝'」。(四1995年剛:19)
對象適配器:
$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');
類適配器
MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
類適配器使用多重繼承到一個接口適應另:(取決於你的編程語言:Java的& C#不支持多重繼承)
對象適配器取決於對象組成:
像S烏爾斯河:設計模式(可複用面向對象軟件的元素)一書
簡單的話, 類適配器使用子類和對象適配器用組合物使用授權。
實施例:
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的使用對象適配器,
當沒有辦法繼承該類將根據客戶端界面進行調整。例如,當MyExistingServiceClass被聲明爲final時。
當客戶端期望一個不是inteface而是一個抽象類實現的合同。在這種情況下,我們沒有別的辦法,只能繼承客戶的期望類,因爲我們不能爲一個以上的類繼承類,所以除了使用類作爲組合之外別無他法。
abstract class AbstractClientClass {
abstract void display();
}
class MyNewObjectAdapter extends AbstractClientClass {
MyExistingServiceClass existingClassObject;
void display() {
existingClassObject.show();
}
}
當您需要修改多個對象時。這種情況是當你沒有直接使用被修改的對象時。這裏的一個好例子是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上使用。