logo

Wzorzec projektowy metody Singletona

Wzorzec Singleton jest prawdopodobnie najpopularniejszym wzorcem projektowym. Jest to prosty wzór, łatwy do zrozumienia i użycia. Czasami jest używany w nadmiarze i w scenariuszach, w których nie jest wymagany. W takich przypadkach wady jego stosowania przeważają nad korzyściami, jakie ze sobą niesie. Z tego powodu wzór singletonu jest czasami uważany za wzór antywzorzec lub singleton wzorca .

Wzorzec projektowy metody Singletona



Ważne tematy dotyczące wzorca projektowego metody Singletona

1. Czym jest wzorzec projektowy metody Singletona?

Metoda Singleton lub wzorzec Singleton Design to jeden z najprostszych wzorców projektowych. Zapewnia, że ​​klasa ma tylko jedną instancję i zapewnia globalny punkt dostępu do niej.

różnica między lwem a tygrysem

2. Kiedy stosować wzorzec projektowy metody Singletona?

Wzorca projektowego metody Singleton należy używać, gdy:



  • Musi istnieć dokładnie jedna instancja klasy i musi ona być dostępna dla klientów z dobrze znanego punktu dostępu.
  • Kiedy jedyna instancja powinna być rozszerzalna poprzez podklasę, a klienci powinni mieć możliwość korzystania z rozszerzonej instancji bez modyfikowania
  • Klasy Singleton są używane do rejestrowania, obiektów sterowników, buforowania i puli wątków oraz połączeń z bazami danych.

3. Rodzaje inicjalizacji Singletona

Instancję klasy Singleton można utworzyć dwoma metodami:

  • Wczesna inicjalizacja: W tej metodzie klasa jest inicjowana niezależnie od tego, czy ma być używana, czy nie. Główną zaletą tej metody jest jej prostota. Inicjujesz zajęcia w momencie ich ładowania. Jego wadą jest to, że klasa jest zawsze inicjalizowana niezależnie od tego, czy jest używana, czy nie.
  • Leniwa inicjalizacja: W tej metodzie klasa jest inicjowana tylko wtedy, gdy jest to wymagane. Może to uchronić Cię przed tworzeniem instancji klasy, gdy jej nie potrzebujesz. Generalnie, gdy tworzymy klasę singletonową, stosujemy leniwą inicjalizację.

4. Kluczowy element wzorca projektowego metody Singletona:

Kluczowy składnik wzorca projektowego metody Singleton-(1)

4.1. Członek statyczny:

Wzorzec lub wzorzec Singleton Singleton wykorzystuje statyczny element klasy. Ten statyczny element członkowski gwarantuje, że pamięć zostanie przydzielona tylko raz, zachowując pojedynczą instancję klasy Singleton.



Jawa
// Static member to hold the single instance private static Singleton instance;>

4.2. Prywatny konstruktor:

Wzorzec Singleton lub wzór Singleton zawiera prywatny konstruktor, który służy jako barykada przed zewnętrznymi próbami utworzenia instancji klasy Singleton. Dzięki temu klasa ma kontrolę nad procesem tworzenia instancji.

Jawa
// Private constructor to // prevent external instantiation class Singleton {  // Making the constructor as Private  private Singleton()  {  // Initialization code here  } }>

4.3. Statyczna metoda fabryczna:

Kluczowym aspektem wzorca Singletona jest obecność statycznej metody fabrycznej. Metoda ta pełni rolę bramy, zapewniając globalny punkt dostępu do obiektu Singleton. Kiedy ktoś żąda instancji, ta metoda albo tworzy nową instancję (jeśli żadna nie istnieje), albo zwraca istniejącą instancję wywołującemu.

Jawa
// Static factory method for global access public static Singleton getInstance() {  // Check if an instance exists  if (instance == null) {  // If no instance exists, create one  instance = new Singleton();  }  // Return the existing instance  return instance; }>

5. Implementacja wzorca projektowego metody Singleton

Implementację wzorca projektowego Singleton lub wzorca Singleton opisano na poniższym diagramie klas:

Zrzut ekranu-2023-12-07-174635

Implementacja wzorca projektowego metody Singleton

Implementacja wzorca singleton Design jest bardzo prosta i składa się z jednej klasy. Aby mieć pewność, że instancja singletonu jest unikalna, wszystkie konstruktory singletonu powinny być ustawione jako prywatne. Dostęp globalny odbywa się za pomocą metody statycznej, do której można uzyskać globalny dostęp do pojedynczej instancji, jak pokazano w kodzie.

Jawa
/*package whatever //do not write package name here */ import java.io.*; class Singleton {  // static class  private static Singleton instance;  private Singleton()  {  System.out.println('Singleton is Instantiated.');  }  public static Singleton getInstance()  {  if (instance == null)  instance = new Singleton();  return instance;  }  public static void doSomething()  {  System.out.println('Somethong is Done.');  } } class GFG {  public static void main(String[] args)  {  Singleton.getInstance().doSomething();  } }>

Wyjście
Singleton is Instantiated. Somethong is Done.>

Metodą getInstance sprawdzamy, czy instancja ma wartość null. Jeśli instancja nie ma wartości null, oznacza to, że obiekt został utworzony wcześniej; w przeciwnym razie utworzymy go za pomocą operatora new.

6. Różne sposoby implementacji wzorca projektowego metody Singleton

Czasami potrzebujemy tylko jednej instancji naszej klasy, na przykład pojedynczego połączenia DB współdzielonego przez wiele obiektów, ponieważ utworzenie osobnego połączenia DB dla każdego obiektu może być kosztowne. Podobnie w aplikacji może istnieć pojedynczy menedżer konfiguracji lub menedżer błędów, który obsługuje wszystkie problemy, zamiast tworzyć wielu menedżerów.

Klasyczna implementacja

Zobaczmy różne opcje projektowania implementacji takiej klasy. Jeśli dobrze radzisz sobie ze zmiennymi klas statycznych i modyfikatorami dostępu, nie powinno to być trudne zadanie.

Metoda 1 – Klasyczna implementacja || Aby zaimplementować, ustaw funkcję getInstance() na statyczną Wzorzec projektowy metody Singletona

Jawa
// Classical Java implementation of singleton // design pattern class Singleton {  private static Singleton obj;  // private constructor to force use of  // getInstance() to create Singleton object  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

Tutaj zadeklarowaliśmy uzyskac instancje() static, abyśmy mogli ją wywołać bez tworzenia instancji klasy. Pierwszy raz uzyskac instancje() nazywa się, tworzy nowy obiekt singleton, a następnie zwraca ten sam obiekt.

Notatka: Obiekt Singleton nie jest tworzony, dopóki go nie potrzebujemy i nie wywołamy metody uzyskac instancje() metoda. Nazywa się to leniwym tworzeniem instancji. Głównym problemem związanym z powyższą metodą jest to, że nie jest ona bezpieczna dla wątków. Rozważ następującą sekwencję wykonania.

Ta sekwencja wykonania tworzy dwa obiekty dla singletonu. Dlatego ta klasyczna implementacja nie jest bezpieczna dla wątków.

Metoda 2 || Zsynchronizuj funkcję getInstance() w celu wdrożenia Wzorzec projektowy metody Singletona

Jawa
// Thread Synchronized Java implementation of // singleton design pattern class Singleton {  private static Singleton obj;  private Singleton() {}  // Only one thread can execute this at a time  public static synchronized Singleton getInstance()  {  if (obj == null)  obj = new Singleton();  return obj;  } }>

Tutaj użycie synchronized zapewnia, że ​​tylko jeden wątek na raz może zostać wykonany uzyskac instancje() . Główną wadą tej metody jest to, że używanie synchronizacji za każdym razem podczas tworzenia obiektu singleton jest kosztowne i może zmniejszyć wydajność programu. Jeśli jednak wydajność uzyskac instancje() nie ma krytycznego znaczenia dla Twojej aplikacji, ta metoda zapewnia czyste i proste rozwiązanie.

Metoda 3 – Chętna instancja || Implementacja wzorca projektowego singletonu oparta na statycznym inicjatorze

Jawa
// Static initializer based Java implementation of // singleton design pattern class Singleton {  private static Singleton obj = new Singleton();  private Singleton() {}  public static Singleton getInstance() { return obj; } }>

Tutaj utworzyliśmy instancję singletonu w inicjatorze statycznym. JVM wykonuje inicjator statyczny po załadowaniu klasy, co gwarantuje bezpieczeństwo wątków. Używaj tej metody tylko wtedy, gdy klasa singleton jest lekka i jest używana podczas wykonywania programu.

Metoda 4 – Najskuteczniejsza || Użyj podwójnego sprawdzania blokowania, aby zaimplementować wzorzec projektowy singleton

Jeśli uważnie zauważysz, że po utworzeniu obiektu synchronizacja nie jest już przydatna, ponieważ teraz obiekt obj nie będzie miał wartości null i każda sekwencja operacji doprowadzi do spójnych wyników. Zatem blokadę funkcji getInstance() uzyskamy tylko raz, gdy obj ma wartość null. W ten sposób synchronizujemy tylko pierwszą drogę, dokładnie to, czego chcemy.

Jawa
// Double Checked Locking based Java implementation of // singleton design pattern class Singleton {  private static volatile Singleton obj = null;  private Singleton() {}  public static Singleton getInstance()  {  if (obj == null) {  // To make thread safe  synchronized (Singleton.class)  {  // check again as multiple threads  // can reach above step  if (obj == null)  obj = new Singleton();  }  }  return obj;  } }>

Zadeklarowaliśmy obj lotny co zapewnia, że ​​wiele wątków poprawnie oferuje zmienną obj podczas jej inicjowania w instancji Singleton. Ta metoda drastycznie zmniejsza obciążenie związane z każdorazowym wywoływaniem metody synchronized.

7. Przypadek użycia metody Singletona wzorcowego

  • Połączenia z bazą danych: W aplikacjach, w których tworzenie połączeń z bazą danych i zarządzanie nimi jest kosztowną operacją, można zastosować Singleton do utrzymania pojedynczego połączenia z bazą danych w całej aplikacji.
  • Zarządzanie konfiguracją: Jeśli masz globalne ustawienia konfiguracyjne, do których muszą mieć dostęp różne komponenty aplikacji, menedżer konfiguracji Singleton może zapewnić pojedynczy punkt dostępu do tych ustawień.
  • Komponenty graficznego interfejsu użytkownika: W przypadku komponentów lub kontrolerów graficznego interfejsu użytkownika (GUI) Singleton może pomóc w zarządzaniu stanem i działaniami interfejsu użytkownika, zapewniając pojedynczy punkt kontroli.
  • Menedżerowie urządzeń: W systemach wbudowanych lub aplikacjach współpracujących z urządzeniami sprzętowymi Singleton może służyć do zarządzania i kontrolowania dostępu do urządzeń sprzętowych w celu uniknięcia konfliktów.
  • Usługa drukowania: W systemach obejmujących drukowanie dokumentów lub raportów usługa drukowania Singleton może koordynować i zarządzać zadaniami drukowania, zapewniając efektywne wykorzystanie zasobów drukarskich.

8. Zalety wzorca projektowego metody Singletona:

  • Rozwiązuje kolizje nazw: W scenariuszach, w których potrzebny jest pojedynczy punkt kontroli, aby uniknąć konfliktów lub kolizji nazewnictwa, wzorzec Singleton gwarantuje, że istnieje tylko jedna instancja o unikalnej nazwie.
  • Inicjalizacja chętna lub leniwa: Wzorzec Singleton obsługuje zarówno inicjalizację agresywną (tworzenie instancji po załadowaniu klasy), jak i inicjalizację leniwą (tworzenie instancji po pierwszym żądaniu), zapewniając elastyczność w zależności od przypadku użycia.
  • Bezpieczeństwo wątków: Prawidłowo zaimplementowane wzorce Singleton mogą zapewnić bezpieczeństwo wątków, zapewniając, że instancja zostanie utworzona atomowo i że wiele wątków nie utworzy przypadkowo duplikatów instancji.
  • Zmniejszony rozmiar pamięci: W aplikacjach, w których zużycie zasobów jest krytyczne, wzorzec Singleton może przyczynić się do zmniejszenia zużycia pamięci, zapewniając, że istnieje tylko jedna instancja klasy.

9. Wady wzorca projektowego Singleton

  • Trudności testowania: Ponieważ Singletony wprowadzają stan globalny, testowanie jednostkowe może stać się wyzwaniem. Testowanie pojedynczego komponentu może być bardziej skomplikowane, jeśli opiera się on na Singletonie, ponieważ stan Singletona może mieć wpływ na wynik testów.
  • Problemy ze współbieżnością: W środowisku wielowątkowym mogą wystąpić problemy związane z utworzeniem i inicjalizacją instancji Singleton. Jeśli wiele wątków próbuje jednocześnie utworzyć Singleton, może to spowodować sytuację wyścigową.
  • Ograniczona rozszerzalność: Wzorzec Singleton może sprawić, że kod będzie mniej rozszerzalny. Jeśli później zdecydujesz, że potrzebujesz wielu instancji klasy lub chcesz zmienić logikę tworzenia instancji, może to wymagać znacznej refaktoryzacji.
  • Globalna zależność: Wzorzec Singleton tworzy globalną zależność, co utrudnia zastąpienie Singletona alternatywną implementacją lub użycie zastrzyku zależności w celu zapewnienia instancji.
  • Trudne do podklasy: Podklasa Singletona może być wyzwaniem. Ponieważ konstruktor jest zazwyczaj prywatny, rozszerzanie Singletona wymaga dodatkowej uwagi i może nie być zgodne ze standardowymi wzorcami dziedziczenia.
  • Zarządzanie cyklem życia: Wzorzec Singleton może nie obsługiwać scenariuszy, w których instancja musi zostać jawnie zniszczona lub zresetowana. Zarządzanie cyklem życia Singletona może stać się problemem.
  • Globalne nadużycie punktu dostępu: Chociaż globalny punkt dostępu jest zaletą, można go również nadużywać. Programiści mogą ulegać pokusie używania Singletona do wszystkiego, co prowadzi do nadużywania stanu globalnego i mniej modułowej konstrukcji.

10. Wniosek

Ważne jest, aby niektóre klasy miały dokładnie jedną instancję. Chociaż w systemie może być wiele drukarek, powinien być tylko jeden bufor drukarki. Powinien istnieć tylko jeden system plików i jeden menedżer okien. Filtr cyfrowy będzie miał jeden przetwornik A/D. System księgowy będzie dedykowany do obsługi jednej firmy. Jak możemy zapewnić, że klasa ma tylko jedną instancję i że instancja jest łatwo dostępna? Zmienna globalna udostępnia obiekt, ale nie uniemożliwia tworzenia instancji wielu obiektów.

Lepszym rozwiązaniem jest uczynienie samej klasy odpowiedzialnej za śledzenie jej jedynej instancji. Klasa może zapewnić, że nie będzie można utworzyć żadnej innej instancji (przechwytując żądania utworzenia nowych obiektów) i może zapewnić sposób dostępu do instancji. To jest wzór Singletona.