Wzorce projektowe (3)

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

Fabryka abstrakcyjna.

Fabryka abstrakcyjna to wzorzec obiektowy. Jego celem jest dostarczenie interfejsu do tworzenia różnych obiektów jednego typu bez specyfikowania ich konkretnych klas. Umożliwia tworzenie jednemu obiektowi różnych powiązanych ze sobą reprezentacji podobiektów określając ich typ podczas działania programu.

Klasy

class AbstractFactory{/*
tworzy interfejs operacji, które utworzą AbstractProduct
*/};

class ConcreteFactory: public AbstractFactory{/*
implementuje operacje AbstractFactory, typowo istnieje kilka klas ConcreteFactory
*/};

class AbstractProduct{/*
tworzy interfejs dla ConcreteProduct
*/};

class ConcreteProduct: public AbstractProduct{/*
dziedziczy i implementuje AbstractProduct
*/};

class Client{/*
wykorzystuje interfejs AbstractFactory
*/};

Etapy działania

  1. Klient tworzy wskaźnik do obiektu AbstractFactory, do którego przypisuje ConcreteFactory wywołując odpowiednią metodę ustalającą, który obiekt ConcreteFactory ma być stworzony.
  2. Za pomocą fabryki tworzymy obiekty, które nas interesują. Mamy pewność ze np. stworzone obiekty będą poprawne dla danej biblioteki lub systemu, na którym został uruchomiony program.

Konsekwencje

Zalety:

  • możliwość ukrycia szczegółów implementacyjnych klas reprezentujących konkretny produkt – klient widzi tylko
    interfejs,
  • ukryciu ulegają także nazwy tych klas co nie wymusza ich zapamiętania i odizolowuje klienta od problemu określenia, do której klasy należy obiekt.

Wady:

  • minusem jest trudność rozszerzania rodzin obiektów o nowe podobiekty. Wymusza to modyfikacje klas fabryki
    abstrakcyjnej.

Przykład

#include <iostream>
#include <string>
#include <memory>
using namespace std;



///klasa pomocnicza
struct Globals
{
static string os;
};


string Globals::os="windows";


///abstrakcyjny produkt
class Button
{
  public:
    virtual void paint()=0;
    virtual ~Button() {}
};

///konkretny produkt
class WinButton: public Button
{
  public:
    void paint()
    {
      cout<<"Przycisk WinButton"<<endl;
    }
};

class OSXButton: public Button
{
  public:
    void paint()
    {
      cout<<"Przycisku OSXButton"<<endl;
    }
};

///abstract factory
class GUIFactory
{
  public:
    virtual Button* createButton()=0;
    virtual ~GUIFactory() {}
};

//konkretna fabryka
class WinFactory: public GUIFactory
{
  public:
    Button* createButton()
    {
      return new WinButton();
    }
    
};

class OSXFactory: public GUIFactory
{
  public:
    Button* createButton()
    {
      return new OSXButton();
    }
};

GUIFactory* getFactory()
{
  string sys=Globals::os;
  if(sys=="windows")
    return new WinFactory();
  else
    return new OSXFactory();
}


int main(int argc, const char* argv[])
{
  GUIFactory* factory(getFactory());
  Button* button=factory->createButton();
  button->paint();

  delete factory;
  delete button;
}

część 4

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.