Wzorzec projektowy singleton
Ze wzorcami projektowymi bywa różnie. Niektóre są bardzo przydatne, inne mniej, a jeszcze inne są pożądane tylko w określonych sytuacjach. Ogólnie bardzo łatwo wpaść w pułapkę nadużycia określonych rozwiązań. Taka sytuacja ma często miejsce w przypadku wzorca projektowego singleton. Singleton pozwala na stworzenie kodu klasy, która zawsze będzie miała jedną i tę samą instancję. Ogółem ten wzorzec ma więcej zalet — poniżej lista najważniejszych:
- możliwość trzymania jednej instancji klasy per proces aplikacji,
- łatwy dostęp do instancji,
- możliwość przechowywania informacji lub stanu przez cały czas życia aplikacji,
- łatwa implementacja mechanizmu lazy loading.
Oczywiście nie ma rozwiązań idealnych, czego najlepszym przykładem jest właśnie singleton. Poniżej lista kilku istotnych wad:
- instancja żyje przez cały czas życia aplikacji, co oznacza, że wykorzystywane przez nią zasoby zostaną zwolnione dopiero przy zamknięciu aplikacji;
- bardzo trudno jest testować kod aplikacji, która wykorzystuje singletony;
- występuje problem z użyciem IoC;
- wzorzec jest bardzo uzależniający.
W początkowej fazie zauroczenia tym wzorcem programiści często oddają mu się bez reszty i najchętniej tworzyliby aplikacje zbudowane tylko z singletonów, co samo w sobie jest beznadziejnym rozwiązaniem. Singleton w nadmiarze bowiem więcej szkodzi, niż pomaga. Budowa klasy Zastosowanie wzorca singleton sprowadza się właściwie do przygotowania klasy, która ma odpowiednią budowę. Kluczowych jest kilka elementów:
- dostęp do instancji za pomocą statycznej właściwości;
- prywatny konstruktor, który blokuje tworzenie instancji na zewnątrz klasy;
- tworzenie instancji na żądanie (lazy loading);
- modyfikator sealed, który blokuje dziedziczenie z klasy singletonu.
Poniżej przykładowa klasa, która spełnia wszystkie powyższe założenia: [sourcecode language="csharp"] public sealed class MySingleton { private static MySingleton _instance; // Statyczny kod zapewniający dostęp do instancji public static MySingleton Instance { get { if (_instance == null) { _instance = new MySingleton(); } return _instance; } } // Przykładowa metoda public void DoSomething() { Console.WriteLine($"Current value property TestProperty is: {TestProperty}."); } // Przykładowa właściwość public string TestProperty { get; set; } // Prywatny konstruktor blokuje tworzenie instancji na zewnątrz private MySingleton() { } } [/sourcecode] Jak widać, poza specyficznym podejściem do tworzenia nowych obiektów MySingleton jest prawie zwykłym bytem. Przykładowe użycie (gdziekolwiek w kodzie całej aplikacji) jest bardzo proste: [sourcecode language="csharp"] MySingleton.Instance.TestProperty = "lalalala"; MySingleton.Instance.DoSomething(); [/sourcecode] Zgodnie z wcześniejszym listingiem, powyższe wywołanie utworzy instancję klasy MySingleton, a następnie wykona na niej obie operacje. Singleton a IoC Singleton ma swoje wady i zalety i jak wszystko powinien być stosowany z rozwagą. W dzisiejszych czasach istnieje jednak poważna alternatywa dla tego rozwiązania, a jest nią IoC. O ile korzystamy z wystarczająco konfigurowalnego narzędzia (np. Autofac), możemy w łatwy sposób zdefiniować, jak ma być zarejestrowana określona klasa. W popularnym Autofacu wystarczy w tym celu zarejestrować dowolną klasę jako SingleInstance: [sourcecode language="csharp"] var builder = new ContainerBuilder(); builder.RegisterType<MyClass>().As<IMyInterface>().SingleInstance(); var container = builder.Build(); [/sourcecode] Co zyskujemy dzięki takiemu rozwiązaniu? Właściwie wszystko to, co straciliśmy, stosując normalnego singletona:
- możemy swobodnie korzystać z IoC;
- kod wciąż da się łatwo przetestować;
- w razie potrzeby klasę można zarejestrować do pracy w trybie innym niż SingleInstance.
Oczywiście sam kontener IoC jest pewnym narzutem — trzeba go wybrać, zainstalować i skonfigurować. Jeśli mamy prostą i małą aplikację, może on być zbędnym dodatkiem. Dlatego też, o czym już wspominałem, wszystkiego powinniśmy używać z rozwagą!
Zobacz nasze propozycje
-
- Druk
- PDF + ePub + Mobi
(38,35 zł najniższa cena z 30 dni)
35.40 zł
59.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(32,43 zł najniższa cena z 30 dni)
29.94 zł
49.90 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(64,35 zł najniższa cena z 30 dni)
59.40 zł
99.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(41,40 zł najniższa cena z 30 dni)
41.40 zł
69.00 zł (-40%) -
- Druk
Niedostępna
-
- Druk
- PDF + ePub + Mobi
(29,40 zł najniższa cena z 30 dni)
29.40 zł
49.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(38,35 zł najniższa cena z 30 dni)
35.40 zł
59.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(40,20 zł najniższa cena z 30 dni)
40.20 zł
67.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(41,40 zł najniższa cena z 30 dni)
41.40 zł
69.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(29,94 zł najniższa cena z 30 dni)
29.94 zł
49.90 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(71,40 zł najniższa cena z 30 dni)
71.40 zł
119.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(40,20 zł najniższa cena z 30 dni)
40.20 zł
67.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(83,85 zł najniższa cena z 30 dni)
77.40 zł
129.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(44,85 zł najniższa cena z 30 dni)
41.40 zł
69.00 zł (-40%) -
- Druk
(107,40 zł najniższa cena z 30 dni)
107.40 zł
179.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(47,40 zł najniższa cena z 30 dni)
47.40 zł
79.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(99,50 zł najniższa cena z 30 dni)
119.40 zł
199.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(41,40 zł najniższa cena z 30 dni)
41.40 zł
69.00 zł (-40%) -
- Druk
- PDF + ePub + Mobi
(40,20 zł najniższa cena z 30 dni)
40.20 zł
67.00 zł (-40%) -
- ePub + Mobi
- Audiobook MP3
(31,12 zł najniższa cena z 30 dni)
29.90 zł
39.90 zł (-25%)