Wzorce projektowe (14)

Autor: Damian Chodorek • Opublikowany: 24 lipca 2015 • Kategoria: kursy, wzorce projektowe

Most.

Most to wzorzec obiektowy. Jego celem jest oddzielenie abstrakcji obiektu od jego implementacji. Używamy mostu gdy chcemy:

  • odseparować implementację od interfejsu,
  • poprawić możliwość rozbudowy zarówno interfejsu, jak i implementacji,
  • ukryć implementację przed klientem.

Klasy

class Abstraction{/*
klasa abstrakcyjna;
zawiera wskaźnik do obiektu klasy Implementator - adres przekazujemy w konstruktorze
*/};

class AbstractionImpl: publi Abstraction{/*
klasa implementuje metody Abstraction używając wskaźnika do Implementator
*/};

class Implementator{/*
klasa abstrakcyjna;
definiuje interfejs ConcreteImplementator
*/};

/*
klasy implementujące interfejs Implementator
*/
class ConcreteImplementator1: public Implementator{};
class ConcreteImplementator2: public Implementator{};
class ConcreteImplementator3: public Implementator{};

class Client{/*
klient korzysta z klas AbstractionImpl;
w zależności od tego jak ustawi wskaźnik do Implementator, w taki sposób metody będą wykonywane
*/};

Etapy działania

  1. Klient tworzy obiekt AbstractionImpl, np. kwadrat.
  2. Do jego konstruktora przekazuje adres jednego z ConcreteImplementator, np. OGL lub DX.
  3. Wywołuje metodę np. rysuj(). W zależności od wykorzystanego konkretnego implementatora, rysowanie odbędzie się na różne sposoby.

Konsekwencje

  • Oddzielenie interfejsu od implementacji.
  • Implementacja nie jest na stałe przytwierdzona do interfejsu, może być dowolnie zmieniana i modyfikowana nawet w trakcie działania programu.
  • Interfejs i implementator mogą być modyfikowane niezależnie.

Przykład

#include <iostream>
 
using namespace std;
 
//implementor
class RysowanieAPI 
{
public:
    virtual void RysujKolo(const double x, const double y, const double promien)= 0;
    virtual void RysujKwadrat(const double x, const double y, const double bok) = 0;
};
 
// konkretny Implementator 1/2 
class OpenGL : public RysowanieAPI 
{
public:
    void RysujKolo(const double x, const double y, const double promien)
    { 
      cout<<"OpenGL kolo narysowane w "<<x<<":"<<y<<" o promieniu"<<promien<<endl; 
    }
    void RysujKwadrat(const double x, const double y, const double bok)
    {
      cout<<"OpenGL kwadrat narysowany w "<<x<<":"<<y<<" o dl boku: "<<bok<<endl;
    }
};
 
// konkretny implementator 2/2 
class DirectX : public RysowanieAPI
{
public:
    void RysujKolo(const double x, const double y, const double promien)
    {
      cout<<"DirectX kolo narysowane w "<<x<<":"<<y<<" o promieniu "<<promien<<endl; 
    }
    void RysujKwadrat(const double x, const double y,const double bok)
    {
      cout<<"DirectX kwadrat narysowany w "<<x<<":"<<y<<"o boku: "<<bok<<endl;
    }
};
 
//abstrakcja
class Ksztalt
{
public: 
    Ksztalt(double x, double y, double promienLubBok, RysowanieAPI* da) :
	    _x(x), _y(y), _promien(promienLubBok), _bok(promienLubBok), _da(da)
    { 
    }

    virtual void Rysuj() = 0;

protected:
    void RysujKolo()
    { 
      _da->RysujKolo(_x, _y, _promien); 
    }
    void RysujKwadrat()
    {
      _da->RysujKwadrat(_x, _y, _bok);
    }

    double _x, _y, _promien, _bok;
    RysowanieAPI* _da; 
};
 
//konkretny kształt
class Kolo: public Ksztalt
{
public : 
    Kolo(double x, double y, double promien, RysowanieAPI* da) :
        Ksztalt(x, y, promien, da)
    {
    }

public: 
    void Rysuj() { RysujKolo(); }   
};
 

class Kwadrat: public Ksztalt
{
public : 
    Kwadrat(double x, double y, double bok, RysowanieAPI* da) :
      Ksztalt(x, y,bok, da)
    {
    }
	
public: 
    void Rysuj() { RysujKwadrat(); }    
};

int main(int argc, const char* argv[])
{
    OpenGL ogl;
    DirectX dx;

    Kwadrat kw(10,20,30,&ogl);
    kw.Rysuj();
  
    Kolo k(1,2,3,&dx);
    k.Rysuj();
}

część 15

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.