首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象适配器模式和类适配器模式的区别

对象适配器模式和类适配器模式的区别
EN

Stack Overflow用户
提问于 2012-04-02 22:43:56
回答 4查看 30.7K关注 0票数 25

如何决定何时使用对象适配器和何时使用类适配器?

问题陈述:创建社交网站,并提供来自facebook,google plus和orkut的导入功能。我无法决定是使用对象适配器还是使用类适配器。

我看过Adapter Pattern: Class Adapter vs Object Adapter,但无法理解其中的本质区别。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-04-03 01:31:14

主要区别是:

  • Class适配器使用继承,并且只能包装。它不能包装接口,因为根据定义,它必须从某个基类派生。

  • Object适配器使用组合,可以包装类和/或接口。它之所以可以这样做,是因为它包含它包装的类或接口对象实例(作为私有的封装成员)。

区别是微妙的。通常后一种方法(偏爱composition over inheritance)更可取,如我在这里引用的链接中所解释的:

对于功能的重用,

面向对象编程(OOP)有太多众所周知的候选者:继承(白盒重用)和组合(黑盒重用)。如果您试图通过继承类来重用代码,则会使子类依赖于父类。这使得系统在许多情况下变得不必要地复杂,更不容易测试,并使运行时的功能交换变得不必要地困难。作为一名干净的代码开发人员,当您需要决定继承是否合适时,您应该遵循Liskov Substitution Principle (LSP)

组合意味着一个类使用另一个类。通过清晰地定义接口,您将进一步促进解耦。这也会给你带来一个好处,那就是实现可以很容易地被替换。因此,在你开始应用Liskov替换原则之前,考虑一下偏好组合而不是继承的概念,并问问自己,为什么你不应该立即喜欢组合。

“因为继承将子类暴露给它的父类实现的细节,所以人们常说‘继承破坏了封装’”。(四人帮1995:19)

票数 45
EN

Stack Overflow用户

发布于 2015-09-26 17:07:41

简而言之,类适配器使用子类化,对象适配器通过使用组合使用委托。

示例:

代码语言:javascript
复制
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();
    }
}

上面是Class Adapter的一个例子。通过从display()的内部实现调用现有的show()方法,我们已将MyExistingServiceClass调整为ClientInterface。

要将其转换为对象适配器,代码将如下所示:

代码语言:javascript
复制
class MyNewObjectAdapter implements ClientInterface {

    MyExistingServiceClass existingClassObject;

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

现在,当使用对象适配器代替类Adatper时,

  1. 当没有办法子类化将要根据客户端接口进行调整的类时。例如,当MyExistingServiceClass被声明为final时。
  2. 当客户端期望的约定不是接口而是抽象类实现时。在这种情况下,我们没有其他方法,只能子类化客户端的预期类,并且由于我们不能子类化多个类,所以除了使用类作为组合进行调整之外,没有其他方法。

当您需要适配多个对象时,抽象类AbstractClientClass {抽象空显示();}类MyNewObjectAdapter扩展了AbstractClientClass { MyExistingServiceClass existingClassObject;空显示(){ existingClassObject.show();}}

  • 。这种情况是当您不是直接使用要调整对象时。这里的一个很好的例子是javax.swing中的JTable类。该类创建一个GUI (图形用户界面)表组件,其中填充了适配器提供给它的信息。为了显示域中的数据,JTable提供了接受javax.swing.table中定义的TableModel实例的构造函数。JDK通过AbstractTableModel提供了TableModel的现有抽象实现。

类MyTableModel扩展AbstractTableModel { MyDomainObject[] existingDomainObjects[];public int getColumnCount() { return 4;} public int getRowCount() { return existingDomainObjects.length();} public MyDomainObject getValueAt(int i) { return existingDomainObjectsi;} }

在这里,为了与AbstractTableModel一起使用,我们对MyDomainObject进行了修改。

票数 14
EN

Stack Overflow用户

发布于 2012-04-02 22:49:17

对象适配器:

代码语言:javascript
复制
$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');

类适配器

代码语言:javascript
复制
MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9978477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档