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

Til*_*lak 20 design-patterns adapter

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

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

我已经看过Adapter Pattern:Class Adapter vs Object Adapter,但无法理解差异的本质.

Mat*_*att 40

主要区别:

  • 类适配器使用继承,只能包装一个.它无法包装接口,因为根据定义它必须从某个基类派生.

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

差异很微妙.通常后面的方法(有利于组合而不是继承)是优选的,如我在这里引用的链接中所解释的:

面向对象编程(OOP)已经为功能重用提供了众所周知的候选:继承(白盒重用)和组合(黑盒重用).如果您尝试通过从类继承来重用代码,则会使子类依赖于父类.这使得系统在许多情况下不必要地复杂,不太可测试并且使得在运行时的功能交换不必要地变得困难.作为[清洁代码开发人员],当您需要确定继承是否合适时,您应该遵循Liskov替换原则(LSP).

组合意味着一个类使用另一个类.您将通过清楚地定义接口来进一步促进解耦.这也将为您提供可轻松替换实现的优势.因此,在开始应用Liskov Substitution的原则之前,请考虑一下"赞成组合而不是继承"概念,并问你十二,为什么你不应该立即选择组合.

"因为继承将子类暴露给其父实现的细节,所以通常会说'继承会破坏封装'".(Gang of Four 1995:19)


Sha*_*war 9

简单来说, 类适配器使用子类和对象适配器使用组合使用委托.

例:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

以上是类适配器的示例.我们通过从display()的内部实现中调用现有的show()方法,将MyExistingServiceClass调整为ClientInterface.

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

class MyNewObjectAdapter implements ClientInterface {

    MyExistingServiceClass existingClassObject;

    void display() {
        existingClassObject.show();
    }
} 
Run Code Online (Sandbox Code Playgroud)

现在何时使用Object适配器代替Class Adatper,

  1. 当没有办法根据客户端的界面对要调整的类进行子类化时.例如,当MyExistingServiceClass被声明为final时.

  2. 当客户期望合同不是接口而是抽象类实现时.在这种情况下,除了子类化客户端的期望类之外别无他法,因为我们不能将多个类子类化,除了使用该类作为组合之外,没有其他方法.

    abstract class AbstractClientClass {
        abstract void display();
    }
    
    class MyNewObjectAdapter extends AbstractClientClass { 
    
        MyExistingServiceClass existingClassObject;
    
        void display() {
            existingClassObject.show();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 当您需要调整多个对象时.这种情况是指您不直接使用对象进行调整.这里一个很好的例子是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];
    }
    }
    
    Run Code Online (Sandbox Code Playgroud)

在这里,我们调整了MyDomainObject以便与AbstractTableModel一起使用.


bur*_*zum 6

对象适配器:

$Adapter = new MyEngine(new MyAdapter($options));
$Adapter->write('something');
Run Code Online (Sandbox Code Playgroud)

类适配器

MyAdapter extends BaseAdapter implements AdapterInterface { ... }
$Adapter = new MyAdapter($options);
$Adapter->write('something');
Run Code Online (Sandbox Code Playgroud)