如何决定何时使用对象适配器以及何时使用类适配器?对象适配器模式和类适配器模式之间的区别
问题说明: 要创建社交网站并提供来自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上使用。