2012-04-02 178 views

回答

24

的主要区别:

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

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

区别是微妙的。通常(有利于composition over inheritance)的后一种方法是优选的,因为在我将在这里引用的链接解释说:

为 重用的功能面向对象编程(OOP)已经太出名的候选人:继承(白盒重用)和合成 (黑盒重用)。如果您尝试通过从类 中获取来重用代码,您将使子类依赖于父类。这使得在许多情况下系统不必要地复杂,不易测试,并且使得在运行时功能的交换不必要地困难。作为[Clean Code Developer] 当您需要决定继承是否合适时,您应该遵循Liskov Substitution Principle (LSP)

构图意味着一个班级使用另一个班级。您将通过明确定义界面来进一步促进解耦。这也将 给你的优势,实现可以很容易地取代。所以 在开始应用Liskov替换原理之前,请考虑 关于继承概念的构成组合,并要求 您还有12个为什么不应该立即选择构图。

“由于继承公开其子类的细节,其父实现的细节,它通常被称为'继承打破 封装'”。(四1995年刚:19)

4

对象适配器:

$Adapter = new MyEngine(new MyAdapter($options)); 
$Adapter->write('something'); 

类适配器

MyAdapter extends BaseAdapter implements AdapterInterface { ... } 
$Adapter = new MyAdapter($options); 
$Adapter->write('something'); 
1

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

enter image description here

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

enter image description here

像S乌尔斯河:设计模式(可复用面向对象软件的元素)一书

4

简单的话, 类适配器使用子类和对象适配器用组合物使用授权。

实施例:

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的使用对象适配器,

  1. 当没有办法继承该类将根据客户端界面进行调整。例如,当MyExistingServiceClass被声明为final时。

  2. 当客户端期望一个不是inteface而是一个抽象类实现的合同。在这种情况下,我们没有别的办法,只能继承客户的期望类,因为我们不能为一个以上的类继承类,所以除了使用类作为组合之外别无他法。

    abstract class AbstractClientClass { 
        abstract void display(); 
    } 
    
    class MyNewObjectAdapter extends AbstractClientClass { 
    
        MyExistingServiceClass existingClassObject; 
    
        void display() { 
         existingClassObject.show(); 
        } 
    } 
    
  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]; 
    } 
    } 
    

在这里,我们已经适应MyDomainObject为了与AbstractTableModel上使用。