Singleton – nazywany również antywzorcem zalicza się do grupy wzorców kreacyjnych (konstrukcyjnych), ponieważ jak nazwa grupy wskazuje, jest on odpowiedzialny za kontrolę tworzenia instancji klas i umożliwia utworzenie tylko jednego obiektu danej klasy.
Dostęp do tworzonych instancji uzyskuje się przez publiczną metodę statyczną.
Jak wiemy, obiekt klasy Application może wystąpić tylko jeden, w odróżnieniu od np. klasy Form.
Dostęp do instancji klasy Application uzyskujemy za pomocą wspomnianej metody statycznej:
#include <Fapp.h> Application* app = Application::GetInstance();
Obiekt klasy zostaje stworzony w momencie pobrania jej instancji w metodzie GetInstance(). W przypadku frameworka bada następuje to jeszcze wcześniej, podczas uruchamiania aplikacji, więc metoda ta zwraca tylko aktualną instancję.
Stworzony obiekt zostaje zapisany w prywatnej zmiennej statycznej klasy Application, dzięki czemu, po ponownym wywołaniu metody GetInstance() zostanie zwrócony uprzednio utworzony obiekt.
Dla przykładu napiszemy prostą klasę, która będzie odpowiedzialna za ograniczenie tworzenia obiektów do jednego. Taką przykładową klasą będzie klasa odpowiedzialna za przechowywanie i zwracanie uchwytu do bazy danych. Klasa oparta na wzorcu Singleton jest klasą globalną, także z dowolnego miejsca w naszym projekcie, będziemy mieli do niej dostęp!
/* * AppRegistry.h * * Created on: 2011-05-10 * Author: markac */ #ifndef APPREGISTRY_H_ #define APPREGISTRY_H_ #include <FIo.h> class AppRegistry { private: static Osp::Io::Database* db; AppRegistry(); public: virtual ~AppRegistry(); static Osp::Io::Database* GetDatabase(); }; #endif /* APPREGISTRY_H_ */
/* * AppRegistry.cpp * * Created on: 2011-05-10 * Author: markac */ #include "AppRegistry.h" Osp::Io::Database* AppRegistry::db = null; AppRegistry::AppRegistry() { // TODO Auto-generated constructor stub } AppRegistry::~AppRegistry() { // TODO Auto-generated destructor stub } Osp::Io::Database* AppRegistry::GetDatabase() { if (db == null) { db = new Osp::Io::Database(); result r = db->Construct(L"/Home/myDatabase.sqlite", false); if (IsFailed(r)) { AppLog("AppRegistry::GetDatabase Failed"); return null; } else { AppLog("AppRegistry::GetDatabase Success"); return db; } } else { AppLog("AppRegistry::GetDatabase Success"); return db; } }
Jak widzisz, klasa jest bardzo prosta, ponieważ chciałem skupić się na zaprezentowaniu działania wzorca Singleton. Aby skorzystać z naszej klasy, dołączamy nagłówek AppRegistry.h do naszego projektu i wywołujemy w następujący sposób:
#include "AppRegistry.h" Database* db = AppRegistry::GetDatabase(); if (db == null) { AppLog("Nie udało się nawiązać połączenia z bazą danych."); } else { // Operacje na bazie danych... // Na końcu zamykamy połączenie: delete db; }
Nie chcę Ci w tym momencie mieszać w głowie, ale nazwa klasy nie jest przypadkowa 🙂 AppRegistry pierwotnie (po wycięciu zbędnych rzeczy) była implementacją innego wzorca o nazwie Registry :-).
W platformie bada OS występuje już klasa o tej nazwie, a mianowicie Osp::App::AppRegistry (także oparta o ten wzorzec), dlatego ważne jest użycie odpowiednich przestrzeni nazw.
O wzorcu Registry napiszę następnym razem.
To co może wydawać się Tobie dziwne, to konstruktor prywatny… Co to oznacza? Przecież konstruktor zawsze był publiczny!
Za tworzenie instancji obiektu odpowiedzialna jest funkcja GetInstance() i tylko taki sposób daje nam kontrolę nad ilością tworzonych instancji.
Jeśli spróbujemy stworzyć obiekt za pomocą operatora new:
AppRegistry appRegistry = new AppRegistry();
po prostu nam się to nie uda. W ten sposób nie mielibyśmy żadnej kontroli nad nad ilością tworzonych instancji klasy AppRegistry.
One thought to “Wzorzec projektowy Singleton”
Komentarze są zamknięte.