オブジェクトアダプターを使用するタイミングとクラスアダプターを使用するタイミングを決定する方法
問題の説明:ソーシャルネットワーキングのWebサイトを作成し、facebook、google plus、orkutからインポート機能を提供します。オブジェクトアダプターとクラスアダプターのどちらを使用するかを決定できません。
私は アダプタパターン:クラスアダプタvsオブジェクトアダプタ を見てきましたが、違いの本質を理解できませんでした。
主な違い:
クラスアダプタは継承を使用し、クラス。定義上、一部の基本クラスから派生する必要があるため、インターフェースをラップすることはできません。
Object Adapterはcompositionを使用し、クラスまたはインターフェース、あるいはその両方をラップできます。プライベートなカプセル化されたメンバーとして、それがラップするクラスまたはインターフェースobject instanceを含むため、これを行うことができます。
違いは微妙です。通常、ここで引用するリンクで説明されているように、(継承よりも 構成を優先する を優先する)後者のアプローチが推奨されます。
オブジェクト指向プログラミング(OOP)には、機能の再利用のための非常によく知られた候補があります。継承(ホワイトボックスの再利用)とコンポジション(ブラックボックスの再利用)です。クラスから継承してコードを再利用しようとすると、サブクラスが親クラスに依存するようになります。これにより、多くの場合、システムが不必要に複雑になり、テストが難しくなり、実行時の機能の交換が不必要に難しくなります。 [クリーンコード開発者]として、継承が適切かどうかを判断する必要がある場合は、 Liskov Substitution Principle(LSP) に従う必要があります。
合成とは、あるクラスが別のクラスを使用することを意味します。インターフェイスを明確に定義することにより、デカップリングをさらに促進します。また、実装を簡単に置き換えることができるという利点もあります。したがって、リスコフ置換の原則を適用する前に、継承よりも構成を優先する概念について考え、すぐに構成を好むべきではない理由を考えてください。
「継承はサブクラスをその親の実装の詳細に公開するため、「継承はカプセル化を破壊する」としばしば言われます。」 (ギャングオブフォー1995:19)
簡単に言うと、クラスアダプターはサブクラス化を使用し、オブジェクトアダプターは構成を使用して委任を使用します。
例:
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の代わりにObjectアダプタを使用する場合、
クライアントのインターフェースに従って適応されるクラスをサブクラス化する方法がない場合。 MyExistingServiceClassがfinalとして宣言されている場合など。
クライアントが、インターフェイスではなく抽象クラスの実装であるコントラクトを期待している場合。この場合、クライアントの期待されるクラスをサブクラス化する以外に方法はありません。複数のクラスをサブクラス化することはできないため、クラスをコンポジションとして適応させる以外に方法はありません。
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は、TableModelの既存の抽象実装をAbstractTableModelで提供します。
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];
}
}
ここでは、AbstractTableModelで使用できるようにMyDomainObjectを適合させました。
オブジェクトアダプター:
$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');
クラスアダプタ
MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
クラスアダプターは複数の継承を使用して1つのインターフェイスを別のインターフェイスに適合させます(プログラミング言語によって異なります:Java&C#は複数の継承をサポートしていません)
オブジェクトアダプターはオブジェクトの構成に依存します。
画像出典:Design Pattern(Elements of Reusable Object-Oriented Software)本
https://www.journaldev.com/1487/adapter-design-pattern-Java アダプター設計パターンは構造設計パターンの1つであり、2つの無関係なインターフェースが連携して機能できるように使用されます。これらの無関係なインターフェースに参加するオブジェクトは、アダプターと呼ばれます。 -双方向アダプターパターンアダプターパターンの実装には、クラスアダプターとオブジェクトアダプターの2つの方法がありますが、どちらの方法でも同じ結果になります。
クラスアダプタ–このフォームはJava継承を使用し、ソースインターフェイス(この場合はSocketクラス)を拡張します。Object Adapter–このフォームはJavaを使用します。構成とアダプタにはソースオブジェクトが含まれます。