Adapter (design sample)

from Wikipedia, the free encyclopedia

The adapter ( English adapter pattern also -) Case class or the wrapper (from English wrapper called packaging ',' jacket ') - is a design pattern in the field of software development , which the category of the structural pattern (engl. Structural patterns ) belongs. The pattern is used to translate one interface into another. This enables classes with mutually incompatible interfaces to communicate. It is a design pattern known as GoF patterns ( Gang of Four , see Gang of Four ).

use

The adapter is used when an existing class is to be used whose interface does not correspond to the required interface. This occurs particularly when classes to re- designed - such as tool collections or class libraries - should be used. These make their services available through clearly defined interfaces, which as a rule should not be changed and often cannot be changed because they come from third parties. The adapter is also used in the creation of reusable classes when they are to work with independent or unpredictable classes.

UML diagram

The so-called " Gang of Four " ( gang of four ) describes two implementation alternatives. The first is the adapter with delegation (the so-called object adapter ), the second is the adapter with inheritance ( class adapter ).

Adapter with delegation (object adapter)

The adapter has an association with the class to be adapted and forwards the requests by delegation .

The advantage is that the adapter and the underlying service can be exchanged; the entire interface used must be implemented for this, even if only part of the implementation is to be adapted.

Object adapter in UML notation

Object adapters are also known as shell class or wrapper class known. Not only can other classes be encapsulated, but also primitive data types or procedural programming libraries.

Shell classes for primitive data types

One application for envelope classes in object-oriented programming languages is to provide classes for basic data types in order to simplify handling and to provide additional functions . So there are z. As in the programming language Java for the type intclass Integerfor char the class Character or float the class Float (as well as Byte, Short, Long, Boolean and Double). These envelope classes enable the object-oriented handling of primitive data types, for example to include them in a reflection concept .

To simplify the use of envelope classes, so-called autoboxing or boxing was introduced in Java 5 . This technique enables the use of envelope classes in the form familiar from primitive data types. Instead of generating objects using Integer i = new Integer(100)the notation can simply Integer i = 100be used. The reference variable can also be iused as if it were an ordinary intvariable. The simple notation and better readability come at the expense of a considerably poorer execution speed.

Shell classes for procedural libraries

Another important application is the adaptation of a procedural library to an object-oriented software system. The function-oriented services of the library are encapsulated in one or more objects . This form of application can often be found as a facade design sample .

Adapters with inheritance (class adapters)

A class adapter is implemented with the help of multiple inheritance . On the one hand, it inherits the implementation of the class to be adapted. On the other hand, the interface to be implemented. The call is then made by self-delegation .

Class adapter in UML notation

A class adapter can then be used sensibly if the programming language (such as C ++ ) has the required properties (multiple inheritance, private inheritance). Programming languages ​​without private and multiple inheritance are rather unsuitable for this type of adapter. Attempting to circumvent this restriction by combining class inheritance and interface implementation results in the adapter class making all methods available to its clients. Although the construct can be used as an adapter, it is not an adapter in the sense of the GoF book that converts one interface into another.

Advantages and disadvantages

The advantages of a class adapter are that it adapts to exactly one target class and can therefore only overwrite the behavior of the target class. The object adapter can also adapt subclasses.

The disadvantage is that a class adapter cannot be used to automatically adapt subclasses.

actors

The service offers reusable services with a clearly defined interface. The client uses services via incompatible interfaces and falls back on adapted interfaces. The goal defines the interface that the client can use. The adapter adapts the interface of the service to the interface to the client.

Examples

General

The access of the elements of a graphical user interface to the underlying model can be controlled via adapters with delegation . For example, a checkbox can display both a buffered Boolean value and the immediate result of a condition. This pattern is used extensively by Visualworks Smalltalk , among others .

Class adapter

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

Concrete example in C ++

Two libraries were purchased, the implementation of which is not visible and cannot be changed. The first is an algorithmic geometry library . It contains algorithms that work on geometric objects such as circles, straight lines and planes, e.g. B. an algorithm that tests whether two circles intersect. The second is a GUI library that also knows objects such as circles and straight lines and can draw them on the screen.

Now, with the help of the geometry library, it should be determined whether two circles that are present as objects of the GUI library intersect (before they are drawn on the screen).

Unfortunately the interfaces of the two libraries are incompatible. They differ not only in the designation of the classes ( Kreisvs. Circle), but also in the designation and semantics of the methods ( getMittelpunkt()vs. getX()and getY()).

The algorithms of the geometry library only work with the public interface (the interface) of the geometric objects. For Kreisexample, one only needs to be able to provide information about its radius and its center point. It is represented by an abstract class with the corresponding methods getRadius()and getMittelpunkt(). It has no data elements for radius and center, because it could also be defined differently: by two points on the edge that are diametrically opposite each other, by three points on the edge or implicitly as the solution set of the equation . This makes the algorithms independent of the specific representation of the geometric objects. Points, on the other hand, are (specifically) implemented as a structure in the library.

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

The graphic objects contained in the GUI library can be drawn on the screen. CircleInternally, one is represented by three floating point numbers , two for the center point coordinates and one for the radius. He can provide information about his geometry ( getX()etc.):

// 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 */}
};

The interfaces of the two libraries are obviously different. In order to be able Circleto Kreisuse one in one of the algorithms for , an adapter for Circleobjects is written. Each adapter object contains one to be adapted Circleand implements the interface of 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()); }
};

Now two Circlefrom the GUI library can be Kreistested for intersection with the algorithm from the geometry library:

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 {
    ...
  }
}

Related design patterns

Bridge and adapter are similar. The bridge, however, is a deliberate design decision to separate an interface from its implementation, while the adapter is used to subsequently adapt one interface to another.

Facade and adapter are a form of the envelope class. However, the facade hides the functional scope of a library in whole or in part, while the adapter only changes the interface.

Web links

Commons : Adapter (design pattern)  - collection of images, videos and audio files
Wikibooks: Pattern: Adapter  - Learning and teaching materials

Individual evidence

  1. Generic Programming without Generics from JAVA5 .  ( Page no longer available , search in web archivesInfo: The link was automatically marked as defective. Please check the link according to the instructions and then remove this notice. (PDF; 33 kB) Department of Computer Science; As of July 10, 2011.@1@ 2Template: dead link / informatik.unibas.ch  
  2. Erich Gamma , Richard Helm , Ralph Johnson , John Vlissides : Design pattern . 5th edition. Addison-Wesley , 1996, ISBN 3-8273-1862-9 , pp. 171 .
  3. Java 5 new capabilities, especially Autoboxing Oracle
  4. private inheritance . Retrieved June 23, 2019 .