Singelton w C# implementacja

singletonumlNie dawno zostałem zapytany o implementacje wzorca projektowego Singelton w C#. O ile wiedziałem ogólne założenia i powód stosowania to nie za bardzo wiedziałem jak zaimplementować go w praktyce. Poniższy krótki wpis postara się odpowiedzieć na pytanie jak zaimplementować ten wzorzec, i kiedy może być on przydatny. Zapraszam do czytania dalej…

1. Do czego przyda się Singleton. 

Singleton stosujemy wszędzie tam kiedy chcemy aby nasza klasa, która go implementuje / stosuje musi mieć tylko jedna i jedyną instancję przez cały okres trwania programu od czasu jej wywołania. Jeżeli chcemy aby nasz obiekt przechowywał te same dane przez cały okres trwania programu to taka klasa nadaję się na kandydata na singeltona, a co z klasą typu static? O tym za chwilę.

2. Przykłady zastosowań:

a) Najprostszym przykładem jest klasa odpowiedzialna za logowanie, przypuśćmy że musimy zaimplementować taką klasę i logować dane do pliku. W tym przypadku nie możemy mieć więcej niż jeden uchwyt do pliku, Singleton pozwoli nam na trzymanie uchwytu od czasu jego pierwszego użycia i każde odniesienie do jej obiektu pozwoli nam logować zdarzenia.

b) Klasa odpowiedzialna z komunikacje z bazą danych, w przypadku kiedy chcemy np. cały czas utrzymywać połączenie z bazą danych i zawsze odnieść się do naszej jedynej jej instancji bez konieczności zamykania połączenia lub co gorsza otwierania wielu połączeń naraz.

c) Klasa w która w swoim obiekcie musi przechowywać dużą ilość danych np. dane konfiguracyjne programu. Tworzenie jej obiektu za każdym jej wywołania powodowało by duże opóźnienia. Nasz Singelton po pierwszym załadowaniu istniał by w pamięci i ponowne odniesienia do jej obiektu zawsze zwracały by już jej zainicjowany obiekt nie powodując opóźnień w działaniu programu.

3. Czym różni się w takim razie od klas typu static ?

Singleton pozwala na przekazywanie swojego obiektu do innych metod i może być traktowany jak normalny obiekt, ponadto bardzo istotne jest też to że może implementować interfejsy. Klasa typu static też ma jedna instancje jak singleton ale może używać tylko statycznych metod.

4. Implementacja

public sealed class Singleton
    {
        //prywatne statyczne pole z inicjalizacją instancji klasy
        private static readonly Singleton instance = new Singleton();

        //prywatne pole pomocnicze do zobrazowania ilosci instancji
        private int counter = 0;

        //Publiczna statyczna właściwość która zwraca obiekt swojej klasy
        //(wykorzystuje do tego pole opisane wyżej)
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }

        //metoda pomocnicza do zobrazowania ilośći instancji
        public void WriteInstanceCounter()
        {
            Console.WriteLine("SINGELTON - licznik wywołań tego samego obiektu: {0}!"
                , counter++);
        }

        // prywatny konstruktor
        private Singleton()
        {
            counter = 1;
        }
    }

Jak widzimy powyżej implementacja składa się z :

  • Klasa jest sealed (blokowanie dziedziczenia)
  • Prywatnego statycznego pola, które zawiera instancję własnej klasy, oraz tworzą ja podczas jej pierwszego wywołania
  • Publicznej statycznej właściwości, która zwraca obiekt swojej klasy (wykorzystuje do tego pole opisane wyżej)
  • Innych metod i pól w zależności od potrzeb, i celu wykorzystania klasy.
  • Prywatnego konstruktora, który zablokuje możliwość tworzenia obiektów tej klasy normalną drogą i zapewni, że dostęp odbywać się będzie jedynie za pomocą naszej statycznej właściwości

5. Wykorzystanie i test działania.

class Program
    {
        static void Main(string[] args)
        {
            for (int nCounter = 0; nCounter < 10; ++nCounter)
            {
                Singleton.Instance.WriteInstanceCounter();
            }
            Console.ReadKey();
        }
    }

Wynik działania programu z przykładowym użyciem singletona.

singleton