2012-04-02 14 views
11

Jak zdecydować, kiedy należy używać adaptera obiektu i kiedy używać adaptera klasy?Różnica między wzorcem adaptera obiektu i wzorcem adaptera klasy

Opis problemu: Aby utworzyć serwis społecznościowy i zapewnić funkcje importowania z Facebooka, Google Plus i Orkut. Nie mogę zdecydować, czy używać adaptera obiektu, czy adaptera klasy.

Spojrzałem na Adapter Pattern: Class Adapter vs Object Adapter, ale nie mogłem zrozumieć istoty różnicy. Adapter

Odpowiedz

24

Główną różnicą:

  • Klasa Adapter wykorzystuje dziedziczenie a może tylko owinąć klasa. Nie może owijać interfejsu, ponieważ z definicji musi pochodzić z pewnej klasy bazowej.

  • obiektu adaptera wykorzystuje kompozycji i można owinąć klas lub interfejsy, lub obu. Może to zrobić, ponieważ zawiera on, jako prywatny, enkapsulowany element, instancję klasy lub interfejsu obiektu , która jest opakowana.

Różnica jest subtelna. Zazwyczaj później podejście (faworyzowanie composition over inheritance) jest korzystne, jak wyjaśniono w linku który Zacytuję tutaj:

Programowanie obiektowe (OOP) jest zbyt dobrze znane kandydatów na ponowne wykorzystanie funkcjonalności: Dziedziczenie (repozytorium whitebox) i Kompozycja (ponowne użycie blackboxa). Jeśli spróbujesz ponownie użyć kodu przez inheriowanie z klasy , podklasa będzie zależna od klasy nadrzędnej. To sprawia, że ​​system jest w wielu przypadkach niepotrzebnie złożony, mniej testowalny i sprawia, że ​​wymiana funkcji w czasie wykonywania staje się niepotrzebnie trudna. Jako programista [Clean Code Developer] powinieneś postępować zgodnie z Liskov Substitution Principle (LSP), gdy musisz się zdecydować, czy dziedziczenie jest właściwe.

Kompozycja oznacza, że ​​jedna klasa używa drugiej. Będziesz dalej promować rozłączanie, definiując wyraźnie interfejsy. To także zapewni korzyść, którą można łatwo zastąpić. Tak więc zanim zaczniesz stosować zasadę Liskov Substitution, pomyśl o o koncepcji Skład na temat Dziedziczenia i zapytaj: , dlaczego nie powinieneś preferować kompozycji od razu.

"Ponieważ dziedziczność ujawnia podklasę szczegółom implementacji jej rodzica , często mówi się, że" dziedziczenie łamie się " enkapsulacji" ".(Gang of Four 1995: 19)

4

obiektu:

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

Adapter Class

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

Adapter klasa używa wielokrotnego dziedziczenia w celu dostosowania jednego interfejsu do drugiego: (w zależności od języka programowania: Java & C# nie obsługuje wielokrotne dziedziczenie)

enter image description here

adapter obiektu zależy od składu obiektu:

enter image description here

obrazy S ródło: Pattern Design (Elementy wielokrotnego użytku oprogramowania obiektowego) książka

4

w prostych słowach, Klasa Adapter wykorzystuje Utworzenie podklasy i Adapter używa obiektu delegację stosując kompozycję.

przykład:

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

Powyższy przykład klasy adaptera. Adaptowaliśmy MyExistingServiceClass do ClientInterface, wywołując istniejącą metodę show() z poziomu wewnętrznej implementacji display().

Aby przekonwertować to do obiektu adaptera, kod będzie jak:

class MyNewObjectAdapter implements ClientInterface { 

    MyExistingServiceClass existingClassObject; 

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

Teraz kiedy używać adaptera obiektu w miejsce klasy Adatper,

  1. Kiedy nie ma sposobu, aby podklasy klasa, która zostanie dostosowana zgodnie z interfejsem klienta. Przykłady takie jak, gdy MyExistingServiceClass jest deklarowana jako ostateczna.

  2. Gdy klient oczekuje umowy, która nie jest inteface, ale jest implementacją klasy abstrakcyjnej. W tym przypadku nie mamy innego sposobu, jak podklasy oczekiwanej klasy klienta, a ponieważ nie możemy podklasować więcej niż jednej klasy, nie ma innego sposobu, niż użycie klasy do zaadoptowania jako kompozycji.

    abstract class AbstractClientClass { 
        abstract void display(); 
    } 
    
    class MyNewObjectAdapter extends AbstractClientClass { 
    
        MyExistingServiceClass existingClassObject; 
    
        void display() { 
         existingClassObject.show(); 
        } 
    } 
    
  3. Kiedy trzeba dostosować więcej niż jeden obiekt. Taki przypadek występuje wtedy, gdy nie pracujesz bezpośrednio z obiektem, który chcesz zaadaptować. Dobrym przykładem jest klasa JTable w javax.swing. Ta klasa tworzy komponent tabeli GUI (graficzny interfejs użytkownika) wypełniony informacjami, które adapter przekazuje do niego. Aby wyświetlić dane z twojej domeny, JTable dostarcza konstruktorów, które akceptują instancję TableModel zdefiniowaną w javax.swing.table. JDK zapewnia istniejącą, abstrakcyjną implementację TableModel z 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]; 
    } 
    } 
    

Tutaj przystosowały MyDomainObject w celu użycia z AbstractTableModel.

Powiązane problemy