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
- Klient tworzy obiekt
AbstractionImpl
, np. kwadrat. - Do jego konstruktora przekazuje adres jednego z
ConcreteImplementator
, np. OGL lub DX. - 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();
}