2012-04-02 2 views
11

Как решить, когда использовать адаптер объекта и когда использовать адаптер класса?Разница между шаблоном адаптера объекта и шаблоном адаптера класса

Заявление о проблемах: Чтобы создать веб-сайт социальных сетей и обеспечить импортную функциональность из facebook, google plus и orkut. Я не могу решить, следует ли использовать адаптер объекта или адаптер класса.

Я посмотрел Adapter Pattern: Class Adapter vs Object Adapter, но не смог понять суть разницы. Адаптер

ответ

24

Основное различие:

  • Класс адаптер использует наследование и может обернуть только класс. Он не может обернуть интерфейс, поскольку по определению он должен выводиться из некоторого базового класса.

  • Объект адаптер использует состав и может обернуть классы или интерфейсы, или обоих. Он может это сделать, поскольку он содержит в качестве закрытого инкапсулированного элемента класс или интерфейс экземпляр объекта он обертывает.

Разница тонкая. Обычно позже подход (в пользу composition over inheritance) является предпочтительным, как описано в ссылке, которую я цитирую здесь:

объектно-ориентированное Programing (ООП) была слишком хорошо известных кандидатов на повторного использования функциональных возможностей: Наследование (использование белого ящика) и Состав (повторное использование черных ящиков). Если вы попытаетесь повторно использовать код по наследству из класса , вы сделаете подкласс зависимым от родительского класса. Это делает систему во многих случаях излишне сложной, менее проверяемой и делает ненужным обмен функциональностью во время выполнения. В качестве [разработчика чистого кода] вы должны следовать Liskov Substitution Principle (LSP), когда вам необходимо решить, подходит ли наследование.

Композиция означает, что один класс использует другой. Далее вы найдете , чтобы обеспечить развязку, четко определяя интерфейсы. Это также будет , что дает вам преимущество в том, что реализации можно легко заменить. Итак, , прежде чем приступать к замене Лискова Замена, подумайте о концепции предпочтения Композиции над Наследством и спросите yourselve, почему вы не должны предпочитать композицию сразу.

«Поскольку наследование предоставляет подкласс для подробностей реализации его родителя , часто говорят, что« наследование прерывает инкапсуляцию ».(Банда Четырех 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 сходный код: Design Pattern (Элементы повторно используемого объектно-ориентированного программного обеспечения) книга

4

В простых словах, класса Adapter использует подклассов и Object Adapter использует делегирование с помощью композиции.

Пример:

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(); 
    } 
} 

Выше приведен пример адаптера класса. Мы адаптировали MyExistingServiceClass к ClientInterface, вызвав существующий метод show() изнутри реализации display().

Для преобразования объекта адаптера, код будет как:

class MyNewObjectAdapter implements ClientInterface { 

    MyExistingServiceClass existingClassObject; 

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

Теперь, когда использовать адаптер объектов вместо класса Adatper,

  1. Когда нет никакого способа подклассов класс, который будет адаптирован в соответствии с интерфейсом клиента. Например, когда MyExistingServiceClass объявлен окончательным.

  2. Когда клиент ожидает контракт, который не является интуицией, а представляет собой реализацию абстрактного класса. В этом случае у нас нет другого способа, кроме как подклассировать ожидаемый класс клиента, и поскольку мы не можем подклассифицировать более одного класса, нет другого способа, кроме использования класса, который должен быть адаптирован в качестве композиции.

    abstract class AbstractClientClass { 
        abstract void display(); 
    } 
    
    class MyNewObjectAdapter extends AbstractClientClass { 
    
        MyExistingServiceClass existingClassObject; 
    
        void display() { 
         existingClassObject.show(); 
        } 
    } 
    
  3. Когда вам нужно адаптировать несколько объектов. Такой случай - это когда вы не работаете непосредственно с объектом, подлежащим адаптации. Хорошим примером здесь может служить класс JTable в javax.swing. Этот класс создает компонент таблицы графического интерфейса пользователя (GUI), заполненный информацией, которую ваш адаптер передает на него. Чтобы отображать данные из вашего домена, JTable предоставляет конструкторы, которые принимают экземпляр TableModel , определенный в javax.swing.table. JDK предоставляет существующую абстрактную реализацию TableModel с 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]; 
    } 
    } 
    

Здесь мы адаптировали MyDomainObject для того, чтобы использоваться с AbstractTableModel.