Daj Się Poznać Programowanie Wzorce projektow

SINGLETON – JEDEN Z PROSTSZYCH WZORCÓW PROJEKTOWYCH

Ponieważ cykl artykułów dotyczący zasady SOLID dobiegł końca postanowiłem rozpocząć nową serię związaną z Inżynierią Oprogramowania. W dzisiejszym wpisie poznamy jeden z najprostszych do implementacji wzorzec projektowy, a mianowicie Singleton. Ale czy zawsze najprostszy znaczy najgorszy? Już za chwilę wszystko stanie się jasne. Jednak wcześniej…

PO CO W OGÓLE STOSOWAĆ WZORCE PROJEKTOWE

Programując, bardzo często zadajemy sobie pytanie w jaki sposób powinniśmy zaimplementować daną funkcjonalność. Nie chodzi tutaj o to jaki algorytm zastosować (na to zazwyczaj nie ma jednoznacznej odpowiedzi), ale o sposobie implementacji. Właśnie w tym miejscu swoje miejsce znajdują wzorce projektowe, czyli powtarzalne sposoby implementacji fragmentów kodu. Dobry programista powinien korzystać z gotowych i sprawdzonych wzorców, ponieważ tylko wtedy uniknie poświęcenia czasu na wymyślenie sposobu implementacji oraz w znaczący sposób zmniejszy prawdopodobieństwo wystąpienia błędu.

CO TO JEST SINGLETON

Singleton – kreacyjny wzorzec projektowy, którego celem jest ograniczenie możliwości tworzenia obiektów danej klasy do jednej instancji oraz zapewnienie globalnego dostępu do stworzonego obiektu. Niekiedy wzorzec uogólnia się do przypadku wprowadzenia pewnej maksymalnej liczby obiektów, jakie mogą istnieć w systemie. Niektórzy programiści uznają go za antywzorzec, ponieważ łamie zasady projektowania obiektowego, często bywa nadużywany lub sprowadza się do stworzenia obiektowego zamiennika dla zmiennej globalnej.

 

PRZYKŁADOWA IMPLEMENTACJA

using System;
 namespace Singleton
{
    class Program
    {
        static void Main(string[] args)
        {
            Singleton o1 = Singleton.utworzObiekt();
            Singleton o2 = Singleton.utworzObiekt();
            if(o1 == o2)
            {
                Console.WriteLine("Identyczne");
            }
            else
            {
                Console.WriteLine("Różne");
            }
        }
    }
 
    class Singleton
    {
        private static Singleton _obiekt;
         private Singleton(){}
         public static Singleton utworzObiekt()
        {
            if(_obiekt == null)
            {
                _obiekt = new Singleton();
            }
            return _obiekt;
        }
    }
}

 

ZASTOSOWANIE

Wzorca Singleton używa się najczęściej do przechowywania konfiguracji aplikacji, utrzymania połączenia z bazą danych, komponenty dostępne globalnie itp. Nie należy jednak używać wzorca, ponieważ łamie on kilka podstawowych zasad programowania (jest po części zamknięty na rozbudowę, łamie zasadę jednej odpowiedzialności).

ZALETY I WADY SINGLETONA

ZALETY:

1. Nie musi się ograniczać do obsługi pojedynczej instancji klasy, przy niewielkiej zmianie możemy za jego pomocą zarządzać większą ilością obiektów.
2. Klasa zaimplementowana z użyciem tego wzorca może samodzielnie kontrolować liczbę swoich instancji.
3. Proces pobierania instancji klasy nie jest widoczny dla użytkownika. Nie musi on wiedzieć czy instancja danej klasy istnieje czy jest dopiero tworzona.
4. Jeżeli żaden komponent nie zdecyduje się korzystać z klasy, jej instancja nie zostanie utworzona

WADY:

1. Brak elastyczności- już na poziomie kodu określona jest ilość instancji klasy
2. Utrudnione testowanie aplikacji, przez wprowadzenie globalnego stanu
3. Łamie zasadę jednej odpowiedzialności
4. Łamie zasadę otwarte-zamknięte
5. Nie można go rozszerzyć
6. Musi być stosowany ostrożnie w aplikacjach wielowątkowych. Zażądanie instancji klasy przez dwa wątki równocześnie może skutkować utworzeniem niezależnych instancji.

PODSUMOWANIE

Dzisiaj poznaliśmy jeden z podstawowych wzorców projektowych. Singleton pilnuje, aby klasa była reprezentowana maksymalnie przez jedną instancję. Należy jednak rozważnie podchodzić do implementacji tego wzorca, ponieważ nie zawsze jest on najlepszym rozwiązaniem i bardzo często jest on nadużywany.

2 Comments

  1. Wydaje mi się, że w dzisiejszych czasach zamiast pisać singletony, większość po prostu definiuje reguły w kontenerach IoC. Oczywiście fajnie znać też teorię, ale przykład, który tu zaprezentowałeś też nie jest idealny, ponieważ nie jest thread-safe i istnieje szansa na utworzenie więcej niż jednej instancji. Można to zabezpieczyć na kilka sposobów jak użycie lock, statycznego pola (nie mamy wtedy lazy loading), albo zagnieżdżonej klasy ze statycznym polem.

    1. Jasne, masz całkowitą rację. Ale w tych wpisach skupiam się tylko i wyłącznie na teorii i sam dopiero uczę się wzorców. A co do thread-safe zgadzam się, ale masz o tym napisane w jego wadach a dokładniej w punkcie 6. Zastosowałem tutaj jak najprostszy przykład, aby nie utrudniać zbytnio zrozumienia samej idei.

Dodaj komentarz