Blog Dla Programistów C#/.NET

Cześć! Dzisiaj chciałbym przybliżyć Ci jeden z najbardziej rozpoznawalnych (i jednocześnie kontrowersyjnych) wzorców projektowych – Singleton. Wzorzec ten zapewnia istnienie tylko jednej instancji danej klasy w całej aplikacji. Chociaż spotkasz wiele opinii, że Singleton bywa nadużywany, to w pewnych sytuacjach jest wręcz nieoceniony.

Wzorzec Singleton w C#/.NET: Praktyczne Wprowadzenie

Czym jest Singleton?


Singleton to wzorzec projektowy, który zapewnia, że dana klasa ma tylko jedną instancję w skali całej aplikacji i udostępnia globalny punkt dostępu do tej instancji. W praktyce oznacza to, że zamiast tworzyć wiele obiektów tej klasy w różnych miejscach, zawsze odwołujemy się do jednej, wspólnej instancji.

Kluczowe cechy Singletona:

    1. Prywatny konstruktor – uniemożliwia tworzenie obiektów z zewnątrz.
    2. Statyczne pole przechowujące jedyną instancję.
    3. Metoda (lub właściwość) statyczna zwracająca tę jedyną instancję.


Przykład: klasyczny Singleton w C#


Poniżej znajdziesz najprostszy przykład, który często spotkasz w materiałach dotyczących tego wzorca.

public sealed class ClassicSingleton
{
private static ClassicSingleton _instance = null;

// Obiekt 'locker' do obsługi wątków private static readonly object _lock = new object();

// Prywatny konstruktor private ClassicSingleton()
{
// Ewentualna logika inicjująca }

public static ClassicSingleton Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = new ClassicSingleton();
}
}
}
return _instance;
}
}

// Przykładowa metoda singletona public void DoSomething()
{
Console.WriteLine("Singleton is working!");
}
}

Omówienie
    • sealed – zapobiega dziedziczeniu klasy (wzorzec Singleton nie przewiduje rozszerzania tej klasy).
    • Blok lock – zabezpiecza tworzenie instancji w sytuacjach wielowątkowych (np. w aplikacji serwerowej).
    • Prywatny konstruktor – uniemożliwia tworzenie obiektów poza klasą.

Uwaga: Powyższy kod stosuje lazy instantiation – obiekt tworzony jest dopiero wtedy, gdy jest potrzebny, a nie od razu podczas uruchamiania aplikacji.


Kod użycia Singletona


Jak skorzystać z tej klasy w praktyce? To bardzo proste. Zobacz:

class Program
{
static void Main(string[] args)
{
// Pobieramy referencję do jedynej instancji Singletona: var singleton1 = ClassicSingleton.Instance;
var singleton2 = ClassicSingleton.Instance;

// Obie zmienne wskazują na ten sam obiekt if (ReferenceEquals(singleton1, singleton2))
{
Console.WriteLine("singleton1 i singleton2 to ta sama instancja.");
}

// Wywołujemy metodę Singletona singleton1.DoSomething();

Console.ReadLine();
}
}

Efekt? W konsoli zobaczysz komunikat, że to ta sama instancja, a następnie komunikat z metody DoSomething().


Eager vs. Lazy – dwa podejścia do Singletona


1. Eager initialization (wczesna inicjalizacja)

    • Instancja tworzona jest w momencie załadowania klasy (np. przy starcie aplikacji).
    • Łatwiejsza implementacja, ale może niepotrzebnie zajmować zasoby, jeśli w danej sesji aplikacji nigdy nie użyjemy Singletona. 

public sealed class EagerSingleton
{
private static readonly EagerSingleton _instance = new EagerSingleton();

private EagerSingleton()
{
}

public static EagerSingleton Instance => _instance;
}

2. Lazy initialization (późna inicjalizacja)

    • Instancja tworzona jest dopiero w momencie pierwszego wywołania.
    • Często spotykana w aplikacjach o dużym rozmiarze, gdzie zasoby powinny być alokowane tylko w razie potrzeby.
    • Wymaga kontroli wielowątkowości (blokady lock) lub gotowych mechanizmów w .NET (np. Lazy<T>).


Implementacja Singletona z Lazy<T>


W .NET możesz skorzystać z klasy Lazy<T>, która sama troszczy się o bezpieczne tworzenie obiektów w aplikacjach wielowątkowych. Przykład:

public sealed class LazySingleton
{
private static readonly Lazy<LazySingleton> _instance
= new Lazy<LazySingleton>(() => new LazySingleton());

private LazySingleton()
{
// Ewentualna logika inicjująca }

public static LazySingleton Instance => _instance.Value;

public void DoSomething()
{
Console.WriteLine("Lazy singleton is working!");
}
}

Takie rozwiązanie jest bardzo eleganckie i rekomendowane w wielu scenariuszach .NET.


Kiedy używać Singletona?


    • Dostęp do zasobu globalnego – np. loger, cache, menedżer konfiguracji.
    • Przechowywanie stanu – kiedy naprawdę potrzebujesz jednego, wspólnego stanu w aplikacji.
    • Komunikacja zewnętrzna – np. klasa sterująca połączeniem do zewnętrznego urządzenia.

Zachowaj jednak ostrożność – nadużywanie Singletona może prowadzić do trudnego w utrzymaniu kodu, problemów z testowaniem (można stosować wzorzec Dependency Injection, który bywa łatwiejszy w testowaniu) czy do zbyt dużego sprzężenia w aplikacji.


Podsumowanie


Singleton to jeden z pierwszych wzorców projektowych, z jakim stykają się początkujący programiści. Zapewnia istnienie tylko jednej instancji klasy i udostępnia globalny dostęp do niej. Mimo to, należy go używać z rozwagą, ponieważ zbyt częste sięganie po singletony może utrudniać późniejszą rozbudowę i testowanie aplikacji.

Jeśli chcesz poszerzyć swoją wiedzę na temat wzorców projektowych, a także nauczyć się praktycznych umiejętności programowania w C#, serdecznie zapraszam Cię do mojego szkolenia online "Zostań Programistą .NET". Znajdziesz w nim nie tylko omówienie klasycznych wzorców, ale także praktyczne projekty, w których zobaczysz, jak efektywnie korzystać z platformy .NET.
Daj znać w komentarzu, jakie jest Twoje doświadczenie z wzorcem Singleton i w jakich sytuacjach stosujesz go najczęściej!

To wszystkie na dzisiaj. Jeżeli taki artykuł Ci się spodobał, to koniecznie dołącz do mojej społeczności – darmowe zapisy, gdzie będziesz również miał dostęp do dodatkowych materiałów i przede wszystkim bonusów. Do zobaczenia w kolejnym artykule.

Szkolenie Zostań Programistą .NET
Szczegóły == Zostań Programistą .NET ==
Zapisy tylko do piątku do 22:00!
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
CTO & Founder - FindSolution.pl
Programista C#/.NET. Specjalizuje się w Blazor, ASP.NET Core, ASP.NET MVC, ASP.NET Web API, WPF oraz Windows Forms.
Autor bloga ModestProgrammer.pl
Dodaj komentarz

Wyszukiwarka

Szkolenie Zostań Programistą .NET
Szczegóły == Zostań Programistą .NET ==
Zapisy tylko do piątku do 22:00!

Zostańmy w kontakcie!

Dołącz do mojej listy mailowej, aby otrzymywać ciekawe informacje ze świata programowania. Dodatkowo będziesz informowany o nowych artykułach na blogu, a także otrzymasz wyjątkowe rabaty na moje kursy i szkolenia.

    Nienawidzę spamu, dlatego będziesz otrzymywał tylko wartościowe maile. Możesz zrezygnować z subskrypcji w dowolnym momencie ✅

    © Copyright 2025 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Regulamin. Polityka prywatności. Design by Kazimierz Szpin
    Serwis wykorzystuje pliki cookies. Korzystając ze strony wyrażasz zgodę na wykorzystywanie plików cookies. dowiedz się więcej.