Wzorzec Adapter C++/Qt

Zastosowanie

Adapter inaczej nazywany Nakładką (ang. wrapper) to strukturalny wzorzec projektowy, którego zadaniem jest stworzenie spójnego interfejsu dla dwóch niekompatybilnych klas. Adapter przekształca interfejs jednej z klas na interfejs drugiej.

Adapter

Wskazówki praktyczne

Aby stworzyć wspólny interfejs warto zaimplementować klasę z metodami wirtualnymi która będzie częścią wspólną dla niewspółbieżnych klas. Adapter jest używany w przypadku gdy chcemy przysłonić już istniejące interfejsy jednym wspólnym, a nie możemy tego zrobić np. w sytuacji używania bibliotek zewnętrznych do których mamy tylko API. Autorzy często przytaczają przykład różnych wejść (HDMI, VGA) które mają takie same zadania ale różne interfejsy, a klient ma obsługiwać takie same metody (wyświetl, odepnij).

Zalety i wady

Zalety

  • Umożliwia współprace klas których wykorzystanie byłoby utrudnione ze względu na brak spójnych interfejsów.
  • Bardziej przejrzysty kod

Wady:

  • Wymagane jest dziedzicznie co powoduje przyrost plików z klasami (jeżeli stosujemy adapter klasowy)
  • Adapter klasowy jest mniej elastyczny niż Adapter obiektowy np. po dodaniu w naszym przykładzie getScreenShot(), zakrywanie metod wirtualnych jest bezsensowne w przypadku Mp3Player
#include <QDebug>
#include <QString>

class Player
{
    public:
        virtual void play(){}
        virtual void stop(){}
};

class FlashPlayer: public Player
{
    public:
        void play(){ qDebug() << "Play flash file"; }
        void stop(){ qDebug() << "Stop flash file"; }
};

// This is liblary and we cannot change implementatnion
class Mp3Player
{
    public:
        void playSound(){ qDebug() << "Play mp3 file"; }
        void stopSound(){ qDebug() << "Stop mp3 file"; }
};

/* Adapter */
class Mp3Adapter : public Mp3Player, public Player
{
public:
    void play(){playSound();}
    void stop(){stopSound();}

};

int main()
{
    Player *flash = new FlashPlayer();
    //  Player *mp3 = new Mp3Player();  // Błąd !!!
      Player *mp3 = new Mp3Adapter();

    QList <Player *> listPlayers{flash,mp3};

    foreach(Player *play, listPlayers)
        play->play();


    foreach(Player *play, listPlayers)
        play->stop();

    qDeleteAll(listPlayers);

    return 0;
}

Wyjście programu:

Play flash file
Play mp3 file
Stop flash file
Stop mp3 file