Adapter (przykład projektu)

Adapter ( angielski wzór adapter również -) klasa Case lub obwoluta (z angielskiego wrapper zwane opakowanie „” żakiet „) - jest to wzorzec projektowy w dziedzinie rozwoju oprogramowania , którego kategorię wzoru strukturalnego (pol. Wzory strukturalne należy). Wzorzec służy do tłumaczenia jednego interfejsu na inny. Umożliwia to komunikację klas z wzajemnie niezgodnymi interfejsami. Jest to wzorzec projektowy tzw. Wzorca GoF ( Gang of Four, patrz Gang of Four ).

posługiwać się

Adapter jest używany, gdy ma być używana istniejąca klasa, której interfejs nie odpowiada wymaganemu interfejsowi. Dzieje się tak szczególnie wtedy, gdy należy użyć klas do przeprojektowania - takich jak kolekcje narzędzi lub biblioteki klas. Udostępniają one swoje usługi za pośrednictwem jasno zdefiniowanych interfejsów, których z zasady nie należy zmieniać, a często nie można ich zmienić, ponieważ pochodzą od stron trzecich. Adapter jest również używany do tworzenia klas wielokrotnego użytku, gdy mają one pracować z klasami niezależnymi lub nieprzewidywalnymi.

Diagram UML

Tak zwany „ Gang of Four ” ( gang czterech ) opisuje dwie alternatywy implementacji. Pierwszy to adapter z delegacją (tzw. Adapter obiektowy ), drugi to adapter z dziedziczeniem (adapter klasy ).

Adapter z delegacją (adapter obiektowy)

Adapter ma powiązanie z klasą, która ma zostać dostosowana, i przekazuje żądania przez delegację .

Zaletą jest to, że adapter i podstawowa usługa mogą być wymieniane; w tym celu należy zaimplementować cały używany interfejs, nawet jeśli tylko część implementacji ma zostać dostosowana.

Adapter obiektu w notacji UML

Adaptery obiektów są również znane jako klasa powłoki lub znana klasa opakowania . Hermetyzować można nie tylko inne klasy, ale także prymitywne typy danych lub biblioteki programowania proceduralnego.

Klasy powłoki dla pierwotnych typów danych

Jedną z aplikacji dla klas kopert w obiektowych językach programowania jest zapewnienie klas dla podstawowych typów danych w celu uproszczenia obsługi i zapewnienia dodatkowych funkcji . Więc jest z. Podobnie jak w języku programowania Java dla typu intklasy Integerdo char klasy Character lub float klasy Float (jak również Byte, Short, Long, Boolean i Double). Te klasy powłoki umożliwiają zorientowaną obiektowo obsługę pierwotnych typów danych, na przykład w celu uwzględnienia ich w koncepcji odbicia .

Aby uprościć korzystanie z klas kopertowych, w Javie 5 wprowadzono tzw. Autoboxing lub boxing . Technika ta umożliwia użycie klas kopert w formie znanej z pierwotnych typów danych. Zamiast generowania obiektów za Integer i = new Integer(100)pomocą notacji można po prostu Integer i = 100użyć. Zmienna referencyjna może być również iużywana tak, jakby była zwykłą intzmienną. Prosta notacja i lepsza czytelność odbywają się kosztem znacznie niższej szybkości wykonywania.

Klasy powłoki dla bibliotek proceduralnych

Innym ważnym zastosowaniem jest dostosowanie biblioteki proceduralnej do zorientowanego obiektowo systemu oprogramowania. Usługi biblioteki zorientowane na funkcje są zawarte w jednym lub kilku obiektach . Tę formę zastosowania można często znaleźć jako przykład projektu elewacji .

Adapter z dziedziczeniem (adapter klasy)

Adapter klas jest implementowany przy pomocy dziedziczenia wielokrotnego . Z jednej strony dziedziczy implementację klasy do dostosowania. Z drugiej strony interfejs do zaimplementowania. Połączenie jest następnie wykonywane w drodze samodzielnej delegacji .

Adapter klas w notacji UML

Adapter klasy może być rozsądnie używany, jeśli język programowania (taki jak C ++ ) ma wymagane właściwości (dziedziczenie wielokrotne, dziedziczenie prywatne). Języki programowania bez dziedziczenia prywatnego i wielokrotnego są raczej nieodpowiednie dla tego typu adapterów. Próba obejścia tego ograniczenia poprzez połączenie dziedziczenia klas i implementacji interfejsu powoduje, że klasa adaptera udostępnia wszystkie metody swoim klientom. Chociaż konstrukcja może służyć jako adapter, nie jest to adapter w sensie książki GoF, który konwertuje jeden interfejs w inny.

Zalety i wady

Zaletą adaptera klas jest to, że dostosowuje się on do dokładnie jednej klasy docelowej i dlatego może nadpisywać tylko zachowanie klasy docelowej. Adapter obiektów może również dostosowywać podklasy.

Wadą jest to, że adapter klasy nie może służyć do automatycznego dostosowywania podklas.

aktorzy

Usługa oferuje usługi wielokrotnego użytku z jasno zdefiniowanym interfejsem. Klient korzysta z usług za pośrednictwem niekompatybilnych interfejsów i korzysta z dostosowanych interfejsów. Cel definiuje interfejs, z którego może korzystać klient. Adapter dostosowuje interfejs usługi do interfejsu klienta.

Przykłady

Generał

Dostępem elementów graficznego interfejsu użytkownika do modelu bazowego można sterować za pomocą adapterów z delegowaniem . Na przykład pole wyboru może wyświetlać zarówno buforowaną wartość logiczną, jak i natychmiastowy wynik warunku. Ten wzorzec jest szeroko stosowany między innymi przez Visualworks Smalltalk .

Adapter klasy

// C++ Code Beispiel

/* Die Schnittstelle, welche der Adapter implementieren soll */
class UsedInterface {
public:
  UsedInterface();
  virtual void operation() const;
};

/* Die Implementierung, welche der Adapter verwenden soll */
class Adaptee {
public:
  Adaptee();
  void adaptedOperation() const;
};

/* Die eigentliche Adapterklasse */
class Adapter : public UsedInterface, private Adaptee {
public:
  Adapter();
  void operation() const;
};

/* Implementierung des Adapters */
void Adapter::operation() const {
  Adaptee::adaptedOperation();
}

Konkretny przykład w C ++

Zakupiono dwie biblioteki, których realizacji nie widać i nie można ich zmienić. Pierwsza to algorytmiczna biblioteka geometrii . Zawiera algorytmy działające na obiektach geometrycznych, takich jak okręgi, linie proste i płaszczyzny, np. B. algorytm sprawdzający, czy przecinają się dwa okręgi. Druga to biblioteka GUI, która zna również obiekty, takie jak okręgi i linie proste, i może rysować je na ekranie.

Teraz za pomocą biblioteki geometrii należy ustalić, czy dwa okręgi, które są obecne jako obiekty w bibliotece GUI, przecinają się (zanim zostaną narysowane na ekranie).

Niestety interfejsy obu bibliotek są niekompatybilne. Różnią się one nie tylko oznaczeniem klas ( Kreisvs. Circle), ale także oznaczeniem i semantyką metod ( getMittelpunkt()vs. getX()i getY()).

Algorytmy biblioteki geometrii działają tylko z publicznym interfejsem (interfejsem) obiektów geometrycznych. Na Kreisprzykład wystarczy być w stanie podać informacje o jego promieniu i środku. Jest reprezentowany przez klasę abstrakcyjną z odpowiednimi metodami getRadius()i getMittelpunkt(). Nie ma elementów danych dotyczących promienia i środka, ponieważ można go również określić inaczej: za pomocą dwóch punktów na krawędzi, które są diametralnie przeciwne, przez trzy punkty na krawędzi lub pośrednio jako zbiór rozwiązań równania . To sprawia, że ​​algorytmy są niezależne od określonej reprezentacji obiektów geometrycznych. Z drugiej strony punkty są (konkretnie) implementowane jako struktura w bibliotece.

// Bibliothek für algorithmische Geometrie

struct Punkt {
  double _x, _y; // der Einfachheit halber public
  Punkt(double x, double y) : _x(x), _y(y) {}
};

class Kreis { // abstrakte Klasse, nur Interface
public:
  virtual double getRadius()      const = 0;
  virtual Punkt  getMittelpunkt() const = 0;
};

// Die Implementierung dieser Funktion stützt sich rein auf die
// Schnittstelle, also nicht auf konkrete Realisierungen:
bool schneidetKreisKreis(const Kreis& k1, const Kreis& k2) {
  double abstandDerKreise = abstand(k1.getMittelpunkt(), k2.getMittelpunkt());
  return abstandDerKreise <= (k1.getRadius() + k2.getRadius());
}

Obiekty graficzne zawarte w bibliotece GUI można rysować na ekranie. CircleWewnętrznie jedna jest reprezentowana przez trzy liczby zmiennoprzecinkowe , dwie dla współrzędnych punktu środkowego i jedna dla promienia. Potrafi udzielić informacji o swojej geometrii ( getX()itp.):

// GUI-Bibliothek

class GraphicalObject {
  virtual void draw() = 0; // zeichne dich selbst auf den Bildschirm
};

class Circle : public GraphicalObject {
private:
  double _mx, _my; // Mittelpunkt x und y
  double _r;       // Radius
public:
  Circle(double x, double y, double r) : _mx(x), _my(y), _r(r) {}
  double getX() const { return _mx; }
  double getY() const { return _my; }
  double getR() const { return _r;  }
  void draw() { /* zeichne dich mit Bresenham-Algorithmus */}
};

Interfejsy obu bibliotek są oczywiście różne. Aby móc użyć jednego Circlew jednym z algorytmów dla Kreis, Circlenapisany jest adapter dla obiektów. Każdy obiekt adaptera zawiera jeden do dostosowania Circlei implementuje interfejs Kreis:

// Circle-Adapter zur Benutzung eines Circle als Kreis in der
// Geometrie-Bibliothek

class CircleAdapter : public Kreis, private Circle {
public:
  CircleAdapter(const Circle& c) : Circle(c.getX(), c.getY(), c.getR()) {}

  // Hier wird Circle so adaptiert, dass es auf Kreis passt
  double getRadius()      const { return getR(); }
  Punkt  getMittelpunkt() const { return Punkt(getX(), getY()); }
};

Teraz dwa Circlez biblioteki GUI można Kreisprzetestować pod kątem przecięcia z algorytmem z biblioteki geometrii:

int main() {
  // Mit Hilfe der GUI-Bibliothek werden zwei Circles erzeugt
  Circle c1 = Circle(1.0, 0.0, 2.0);
  Circle c2 = Circle(3.0, 0.0, 2.0);

  // dann werden sie in einen Circle-Adapter gesteckt
  CircleAdapter c1Adapter(c1);
  CircleAdapter c2Adapter(c2);

  // anschließend wird die Geometrie-Bibliothek zum Test auf Schnitt benutzt
  if (schneidetKreisKreis(c1Adapter, c2Adapter)) {
    ...
  } else {
    ...
  }
}

Powiązane wzorce projektowe

Mostek i adapter są podobne. Most jest jednak świadomą decyzją projektową, aby oddzielić interfejs od jego implementacji, podczas gdy adapter jest używany do późniejszego dostosowania jednego interfejsu do drugiego.

Fasada i adapter są formą klasy kopert. Fasada ukrywa w całości lub w części funkcjonalność biblioteki, a adapter zmienia jedynie interfejs.

linki internetowe

Commons : Adapter (wzorzec projektowy)  - zbiór obrazów, filmów i plików audio
Wikibooks: Pattern: Adapter  - Materiały do ​​nauki i nauczania

Indywidualne dowody

  1. Programowanie ogólne bez typów ogólnych z JAVA5 .  ( Strona nie jest już dostępna , przeszukaj archiwum internetoweInformacje: Link został automatycznie oznaczony jako uszkodzony. Sprawdź łącze zgodnie z instrukcjami, a następnie usuń to powiadomienie. (PDF; 33 kB) Katedra Informatyki; Stan na 10 lipca 2011 r.@ 1@ 2Szablon: martwy link / informatik.unibas.ch  
  2. Erich Gamma , Richard Helm , Ralph Johnson , John Vlissides : wzorzec projektowy . Wydanie 5. Addison-Wesley , 1996, ISBN 3-8273-1862-9 , s. 171 .
  3. Nowe możliwości Java 5, zwłaszcza Autoboxing Oracle
  4. dziedziczenie prywatne . Źródło 23 czerwca 2019 r .