Design patterns 对象适配器模式和类适配器模式之间的差异

Design patterns 对象适配器模式和类适配器模式之间的差异,design-patterns,adapter,Design Patterns,Adapter,如何决定何时使用对象适配器以及何时使用类适配器 问题陈述: 创建社交网站,并提供facebook、google plus和orkut的导入功能。我无法决定是使用对象适配器还是类适配器 我已经看过了,但无法理解差异的本质。对象适配器: $Adapter = new MyEngine(new MyAdapter($options)); $Adapter->write('something'); 类适配器 MyAdapter extends BaseAdapter implements Ada

如何决定何时使用对象适配器以及何时使用类适配器

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

我已经看过了,但无法理解差异的本质。

对象适配器:

$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');
类适配器

MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
主要区别是:

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

  • 对象适配器使用组合,可以包装类或接口,或包装两者。它可以做到这一点,因为它包含作为私有封装成员的类或接口对象实例

差别是微妙的。通常,后面的方法(优惠)更可取,我将在此处引用链接中对此进行解释:

面向对象的编程(OOP)对于 功能的重用:继承(白盒重用)和组合 (黑盒重用)。如果您试图通过继承类来重用代码 您将使子类依赖于父类。这是一个很好的例子 在许多情况下,系统不必要地复杂,不易测试,并使 在运行时交换功能是不必要的困难。作为[干净的代码开发人员] 当你离开的时候,你应该遵守规则 需要决定继承是否合适

组合意味着一个类使用另一个类。你会更进一步 通过明确定义接口来促进解耦。这也将 使您能够轻松地替换实现。所以 在开始应用Liskov替换原理之前,请思考 关于偏好组合优于继承的概念和问题 你自己也知道为什么你不应该马上就喜欢作文

因为继承将子类暴露于其父类的 实现时,人们常说“继承中断” 封装'。(四人帮1995:19)


类适配器使用多重继承使一个接口适应另一个接口:(取决于您的编程语言:Java&C不支持多重继承)

对象适配器取决于对象组成:

图片来源:设计模式(可重用面向对象软件的元素)一书, 类适配器使用子类化,而对象适配器通过组合使用委托

abstract class AbstractClientClass {
    abstract void display();
}

class MyNewObjectAdapter extends AbstractClientClass { 

    MyExistingServiceClass existingClassObject;

    void display() {
        existingClassObject.show();
    }
}
例如:

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时

  • 当客户端需要一个不是接口而是抽象类实现的契约时。在这种情况下,我们除了对客户机的预期类进行子类化之外没有其他方法,并且由于我们不能对多个类进行子类化,因此除了将类用作组合之外没有其他方法

    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一起使用。

    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];
    }
    }
    
    适配器设计模式是一种结构设计模式,它的使用使两个不相关的接口可以一起工作。连接这些不相关接口的对象称为适配器。 -双向适配器模式 在实现适配器模式时,有两种方法–类适配器和对象适配器–但是这两种方法产生相同的结果

    类适配器–此表单使用java继承并扩展源接口,在我们的示例中是Socket类。 对象适配器–此表单使用Java组合,适配器包含源对象