Narzędzia użytkownika

Narzędzia witryny


singleton

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

singleton [2008/04/15 18:26] (aktualna)
tsuchecki utworzono
Linia 1: Linia 1:
 +<code cpp>
 +/*
 +Autor: Tadeusz Suchecki
  
 +Wzorzec: Singleton
 +
 +Zastosowanie:​ Singleton to wzorzec konstrukcyjny przeznaczony do ograniczania
 +mozliwosci tworzenia obiektow danej klasy do pojedynczej instancji. Ponadto
 +musi zapewniac globalny dostep do istniejacej instancji obiektu.
 +Czesto w aplikacji istnieje potrzeba stworzenia klasy, ktora posiadalaby
 +wylacznie jedna instancje. Zwykle zwiazane to jest z zapewnieniem wiekszej
 +wydajnosci aplikacji, np. przy dostepie do bazy danych, gdzie kazde laczenie
 +sie z baza jest dla aplikacji kosztowne, bo wymaga czasochlonnego
 +uwierzytelnienia i autoryzacji. W tym przypadku sensowniej jest stworzyc jeden
 +obiekt przechowujacy sesje polaczenia i wykorzystac go do przeslania wielu
 +zapytan. Rowniez w mniej krytycznych przypadkach korzystne jest stosowanie
 +wzorca singletonu. Wskazowka do jego uzycia jest sytuacja, gdy potrzebna jest
 +wylacznie jedna instancja obiektu, ktora wywoluje wiele roznych czesci
 +aplikacji. W takich przypadkach tworzenie obiektu, a nastepnie niszczenie
 +go jest marnotrawstwem zasobow pamieci.
 +
 +Opis: Wzorzec singletonu implementuje sie przez stworzenie klasy, ktora posiada
 +statyczna metode, ktora najpierw sprawdza, czy istnieje juz instancja tej klasy
 +- jesli nie istnieje to tworzy ja - i nastepnie zwraca ja przez referencje.
 +Instancja klasy jest przechowywana w prywatnym lub chronionym, statycznym polu,
 +do ktorego dostep ma tylko opisana wyzej metoda. Owa metoda dostepowa jest
 +jedyna droga pozyskania instancji obiektu singletonu - aby uniemozliwic
 +tworzenie dodatkowych instancji w zwykly sposob, czyli przez wywolanie
 +konstruktora,​ deklaruje sie go jako prywatny lub chroniony.
 +Dodatkowa korzyscia z zastosowania takiego rozwiazania jest to, ze caly proces
 +jest niewidoczny dla uzytkownika i nie musi on wiedziec, czy instancja istnieje
 +czy tez nie.
 +*/
 +
 +/*
 +Dobrym przykladem na zastosowanie singletonu jest polaczenie do bazy danych.
 +W przykladzie nie bede zaglebial sie w samo polaczenie i ogranicze do wypisania
 +informacji o id klienta i numerze wywolania. Informacje te powinny pozwolic
 +zauwazyc sposob dzialania obiektu.
 +*/
 +
 +#include <​pthread.h>​
 +#include <​memory>​
 +#include <​iostream>​
 +#include <​string>​
 +#include <​sstream>​
 +
 +/*
 +Mutex potrzebny do synchronizacji wielu watkow
 +*/
 +class Mutex
 +{
 +  public:
 +    Mutex()
 +    { pthread_mutex_init(&​m,​ 0); }
 +
 +    void lock()
 +    { pthread_mutex_lock(&​m);​ }
 +
 +    void unlock()
 +    { pthread_mutex_unlock(&​m);​ }
 +
 +  private:
 +    pthread_mutex_t m;
 +};
 +/*
 +Pomocniczy locker dla wygody
 +*/
 +class MutexLocker
 +{
 +  public:
 +    MutexLocker(Mutex&​ pm): m(pm) { m.lock(); }
 +    ~MutexLocker() { m.unlock(); }
 +  private:
 +    Mutex& m;
 +};
 +/*
 +Singleton - polaczenie do bazy danych ktore w tym programie moze byc tylko
 +jedno. Gdy jest potrzebne a nie istnieje jest tworzone gdy istnieje zwracana
 +jest referencja na istniejace. Po wywolaniu GetData(id) zwraca informacje o
 +numerze wywolania i id klienta wywolujacego.
 +*/
 +class DB_Connection
 +{
 +  public:
 +    static DB_Connection&​ Instance();
 +    int example_data;​
 +    ~DB_Connection() { }
 +    std::string GetData(int id);
 +
 +  protected:
 +    DB_Connection():​ example_data(1) {}
 +    /*
 +    chroniony aby nie dalo sie stworzyc instancji inaczje niz przez Instance();
 +    */
 +
 +  private:
 +    static std::​auto_ptr<​DB_Connection>​ theSingleInstance;​
 +    static Mutex m;
 +};
 +/*
 +Chyba nie wymaga komentarza
 +*/
 +std::string DB_Connection::​GetData(int id)
 +{
 +  std::​ostringstream os;
 +  os<<"​odwolanie nr: "<<​example_data++<<"​ poczynione przez urzytkownika o id "<<​id;​
 +  return os.str();
 +}
 +/*
 +Zapewnienie istnienia jednej instancji.
 +Jesli instancja nie istnieje jest tworzona.
 +Zwracana jest referencja na instancje.
 +*/
 +DB_Connection&​ DB_Connection::​Instance()
 +{
 +    if (theSingleInstance.get() == 0)
 +    {
 +      MutexLocker obtain_lock(m);​
 +      if (theSingleInstance.get() == 0)
 +      {
 +        theSingleInstance.reset(new DB_Connection);​
 +      }
 +    }
 +    return *theSingleInstance;​
 +}
 +
 +std::​auto_ptr<​DB_Connection>​ DB_Connection::​theSingleInstance;​
 +
 +Mutex DB_Connection::​m;​
 +
 +/*
 +Procedura testowa:
 +          kolejno klienci 1,2,3 wywoluja baze
 +*/
 +int main()
 +{
 +    std::cout << DB_Connection::​Instance().GetData(1) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(2) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(3) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(1) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(2) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(3) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(1) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(2) << std::endl;
 +    std::cout << DB_Connection::​Instance().GetData(3) << std::endl;
 +
 +    return 0;
 +}
 +</​code>​
singleton.txt · ostatnio zmienione: 2008/04/15 18:26 przez tsuchecki