
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)
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
Rozmowa kwalifikacyjna. O czym nie wiedzą kandydaci do pracy, czyli sekrety rekrutujących. Wydanie 5(druk)
(28.20 zł najniższa cena z 30 dni)
28,20 zł47,00 zł -
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(53.40 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(65.40 zł najniższa cena z 30 dni)
65,40 zł109,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(22.20 zł najniższa cena z 30 dni)
22,20 zł37,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(druk)
(77.35 zł najniższa cena z 30 dni)
71,40 zł119,00 zł -
(59.40 zł najniższa cena z 30 dni)
59,40 zł99,00 zł -
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(druk)
(57.85 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(druk)
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(40.20 zł najniższa cena z 30 dni)
40,20 zł67,00 zł -
(46.20 zł najniższa cena z 30 dni)
46,20 zł77,00 zł -
(59.40 zł najniższa cena z 30 dni)
59,40 zł99,00 zł -
(41.40 zł najniższa cena z 30 dni)
41,40 zł69,00 zł -
(druk)
(47.40 zł najniższa cena z 30 dni)
47,40 zł79,00 zł -
(53.40 zł najniższa cena z 30 dni)
53,40 zł89,00 zł -
(24.95 zł najniższa cena z 30 dni)
29,94 zł49,90 zł