Singleton (jedináčik)
Singleton je populárny návrhový vzor, ktorý umožňuje zabezpečiť globálny prístup k inštanciu nejakej triedy.
Motivácia
Niekedy v programe potrebujeme zdieľať jednu inštanciu medzi niekoľkými blokmi, objekty atď., Bez toho aby sme ju museli stále odovzdávať v konstruktoru. Ukážkový príklad je databázové pripojenie, celý program pracuje s jedným pripojením a bolo by nepraktické ho stále odovzdávať. Ponúka sa riešenie urobiť triedu poskytujúce databázové API ako statickú. Môže však nastať prípad, kedy sa nám hodí ju mať instanciovatelnou (napr. Niekedy pracujeme s viacerými pripojeniami) alebo používame hotovú triedu, ktorá statická nie je. Vložíme ju teda do Singleton.
Vzor
Vzor je tvorený triedou, ktorá sa stará o to, aby jej inštancie existovala len raz.
Ako prvý musíme užívateľovi zakázať tvoriť inštanciu, toho docielime implementáciou prázdneho privátneho konstruktoru.
Ďalej vytvoríme bežnú inštančný premennú a do nej vložíme inštanciu, ktorú chceme v programe zdieľať. V našom prípade teda inštanciu databázového pripojenia.
Teraz si trieda vytvorí inštanciu seba samého a tú uloží do statickej premennej. Inštanciu má takto v správe trieda a užívateľ sa k nej inak ako cez ňu nedostane, pretože ju nemôže vytvoriť. Máme ju teda úplne pod kontrolou. Inštanciu nastavíme samozrejme ako privátne a tiež len na čítanie.
Nakoniec vytvoríme verejnú metódu, cez ktorú budeme zvonku k inštancii pristupovať. Vnútri inštanciu vrátime.
Ukážkový zdrojový kód (C #)
class Singleton { private Singleton() { } public Databaze databaze = new Databaze('host', 'jmeno', 'heslo'); private static readonly Singleton instance = new Singleton(); public static Singleton vratInstanci() { return instance; } }
Použitie v programe
Na pripojenie potom v programe pristupujeme takto:
Pripojeni pripojeni = Singleton.vratInstanci();
Singleton znamená jedináčik, teda inštancia, ktorá nemá žiadne súrodenca.
Možné modifikácie
Metóda na vrátenie inštancie priamo nabáda k tomu, aby sme inicializácii inštancie vykonali až vo chvíli, keď ju potrebujeme. Kód teda môžeme modifikovať takto:
class Singleton { private Singleton() { } public Databaze databaze = new Databaze('host', 'jmeno', 'heslo'); private static Singleton instance = null; public static Singleton vratInstanci() { if (instance == null) instance = new Singleton(); return instance; } }
Niekedy takto môžeme optimalizovať výkon programu. Verzia nie je thread safe a v prípade, že by sme pracovali s viacerými vláknami, je potrebné dať inicializácii inštancie do Locku.
Nevýhody
Slovo globálne môže byť trochu kontroverzná a Singleton je kvôli tomu niekedy označovaný ako anti-pattern, teda zlý vzor. Hoci Singleton by mal každý programátor poznať, určite to nie je ideálne vzor pre odovzdávanie závislostí v aplikácii. Lepším vyriešením závislosťou je vzor Dependency Injection. Ak vás táto problematika zaujíma, odporúčam náš kurz Softvérové architektúry a depencency injection. Thread-safe napísaný Singleton môže byť výhodné použiť vo viacvláknových aplikáciách.