如何决定何时使用对象适配器以及何时使用类适配器?
问题陈述: 要创建社交网站并从facebook,google plus和orkut提供导入功能。我无法决定是使用对象适配器还是类适配器。
我看过Adapter Pattern: Class Adapter vs Object Adapter,但无法理解差异的本质。
答案 0 :(得分:34)
主要区别:
类适配器使用继承,只能包装类。它无法包装接口,因为根据定义它必须从某个基类派生。
对象适配器使用组合,可以包装类或接口,或两者兼而有之。它可以这样做,因为它包含作为私有的封装成员,它包装的类或接口对象实例。
差异很微妙。通常后面的方法(赞成composition over inheritance)是优选的,正如我在这里引用的链接中所解释的那样:
面向对象编程(OOP)有众所周知的候选人 功能重用:继承(白盒重用)和组合 (黑盒重用)。如果您尝试通过从类继承来重用代码 您将使子类依赖于父类。这样做了 在许多情况下,系统不必要地复杂,不太可测试和制造 在运行时交换功能不必要的困难。作为[清洁代码开发人员] 你应该跟随Liskov Substitution Principle (LSP) 需要决定继承是否合适。
组合意味着一个类使用另一个类。你会进一步 通过清楚地定义接口来促进解耦。那也是 为您提供可轻松替换实施的优势。所以 在开始应用Liskov Substitution的原则之前,请考虑一下 关于遗产构成的遗产概念和问题 十二,为什么你不应该立刻喜欢作文。
“因为继承将子类暴露给其父类的详细信息 实施时,人们经常说'继承中断 封装'“。(Gang of Four 1995:19)
答案 1 :(得分:6)
对象适配器:
$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');
类适配器
MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
答案 2 :(得分:6)
简单来说, 类适配器使用子类,对象适配器使用合成使用委派。
示例:
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();
}
}
现在何时使用Object适配器代替Class Adatper,
当无法根据客户端界面对要调整的类进行子类化时。例如,当MyExistingServiceClass被声明为final时。
当客户希望合约不是接口而是抽象类实现时。在这种情况下,除了子类化客户端的预期类之外别无他法,因为我们不能将多个类子类化,除了使用该类作为组合之外没有其他方法。
abstract class AbstractClientClass {
abstract void display();
}
class MyNewObjectAdapter extends AbstractClientClass {
MyExistingServiceClass existingClassObject;
void display() {
existingClassObject.show();
}
}
当您需要调整多个对象时。这种情况是指您不直接使用对象进行调整。这里一个很好的例子是javax.swing中的JTable类。此类创建一个GUI(图形用户界面)表组件,其中包含适配器提供给它的信息。为了显示域中的数据,JTable提供了接受TableModel实例的构造函数 在javax.swing.table中定义。 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一起使用。
答案 3 :(得分:1)
类适配器使用多重继承来使一个接口适应另一个接口:(取决于您的编程语言:Java& C#不支持多重继承)
对象适配器取决于对象组成:
图像源:设计模式(可重用面向对象软件的元素)一书
答案 4 :(得分:0)
https://www.journaldev.com/1487/adapter-design-pattern-java 适配器设计模式是结构设计模式之一,它的使用使两个不相关的接口可以一起工作。加入这些不相关接口的对象称为适配器。 -双向适配器模式 在实现Adapter模式时,有两种方法-类适配器和对象适配器-但是,这两种方法都会产生相同的结果。
类适配器 –这种形式使用Java继承并扩展了源接口,在我们的例子中是Socket类。 对象适配器 –此表单使用Java组合,并且适配器包含源对象。