W programowaniu obiektowym pojedyncza klasa Java to klasa, która może mieć tylko jeden obiekt (instancję klasy) na raz. Jeśli po raz pierwszy spróbujemy utworzyć instancję klas Java Singleton, nowa zmienna wskazuje również na pierwszą utworzoną instancję. Zatem wszelkie modyfikacje, jakie dokonamy w dowolnej zmiennej wewnątrz klasy poprzez dowolną instancję, wpływają na zmienną pojedynczej utworzonej instancji i są widoczne, jeśli uzyskujemy dostęp do tej zmiennej poprzez dowolną zmienną zdefiniowanego typu tej klasy.
Pamiętaj o kluczowych punktach podczas definiowania klasy jako klasy singleton, czyli podczas projektowania klasy singleton:
- Ustaw konstruktora jako prywatnego.
- Napisz metodę statyczną, która ma obiekt typu zwracanego tej klasy singleton. W tym przypadku do napisania tej metody statycznej zastosowano koncepcję leniwej inicjalizacji.
Cel klasy Singleton
Podstawowym celem klasy Singleton w języku Java jest ograniczenie liczby utworzonych obiektów do tylko jednego. Często zapewnia to kontrolę dostępu do zasobów, na przykład gniazda lub połączenia z bazą danych.
sortuj listę tablic Java
W przypadku użycia klasy singleton nie dochodzi do marnowania miejsca w pamięci, ponieważ ogranicza to tworzenie instancji. Ponieważ utworzenie obiektu nastąpi tylko raz, a nie za każdym razem, gdy zostanie złożone nowe żądanie.
Możemy używać tego pojedynczego obiektu wielokrotnie, zgodnie z wymaganiami. To jest powód, dla którego aplikacje wielowątkowe i bazy danych najczęściej korzystają ze wzorca Singleton w Javie do buforowania, rejestrowania, łączenia wątków, ustawień konfiguracyjnych i wielu innych.
Przykładowo, mamy przy sobie licencję, a mamy tylko jedno połączenie z bazą danych lub załóżmy, że nasz sterownik JDBC nie pozwala nam na wielowątkowość, wówczas wkracza klasa Singleton i pilnuje, aby w danej chwili tylko jedno połączenie lub pojedynczy wątek może uzyskać dostęp do połączenia.
Jak zaprojektować/utworzyć klasę Singleton w Javie?
Aby utworzyć klasę singleton, musimy wykonać kroki podane poniżej:
1. Upewnij się, że istnieje tylko jedna instancja klasy.
2. Zapewnij globalny dostęp do tej instancji poprzez
- Deklarowanie wszystkich konstruktorów klasy jako prywatnych.
- Udostępnienie metody statycznej, która zwraca odwołanie do instancji. Do pisania metod statycznych używana jest koncepcja leniwej inicjalizacji.
- Instancja jest przechowywana jako prywatna zmienna statyczna.
Przykładem klas singletonowych jest Klasa wykonawcza, serwlet akcji i lokalizator usług . Prywatni konstruktorzy i metody fabryczne są również przykładem klasy singleton.
Różnica między klasą normalną a klasą Singleton
Klasę Singleton możemy odróżnić od zwykłych klas ze względu na proces tworzenia instancji obiektu klasy. Aby utworzyć instancję normalnej klasy, używamy konstruktora Java. Z drugiej strony, aby utworzyć instancję klasy singleton, używamy metody getInstance().
Inna różnica polega na tym, że zwykła klasa znika pod koniec cyklu życia aplikacji, podczas gdy klasa singleton nie ulega zniszczeniu wraz z zakończeniem aplikacji.
Formy wzorca klas Singleton
Istnieją dwie formy wzorców projektowych singletonu, którymi są:
- Wczesna instancja: Tworzenie obiektu odbywa się w momencie ładowania.
- Leniwa instancja: Tworzenie obiektu odbywa się zgodnie z wymaganiami.
Realizacja: Przyjrzyjmy się pokrótce, czym klasa singleton różni się od normalnej klasy w Javie. Tutaj różnica polega na tworzeniu instancji, ponieważ w przypadku normalnej klasy używamy konstruktora, podczas gdy w przypadku klasy singleton używamy metodę getInstance(). które będziemy obserwować w przykładzie 1, jak pokazano poniżej. Ogólnie rzecz biorąc, aby uniknąć nieporozumień, podczas definiowania tej metody możemy również użyć nazwy klasy jako nazwy metody, co zostanie przedstawione w przykładzie 2 poniżej.
Przykład 1:
Jawa
para Java
// Java program implementing Singleton class> // with using getInstance() method> // Class 1> // Helper class> class> Singleton {> > // Static variable reference of single_instance> > // of type Singleton> > private> static> Singleton single_instance => null> ;> > // Declaring a variable of type String> > public> String s;> > // Constructor> > // Here we will be creating private constructor> > // restricted to this class itself> > private> Singleton()> > {> > s => 'Hello I am a string part of Singleton class'> ;> > }> > // Static method> > // Static method to create instance of Singleton class> > public> static> synchronized> Singleton getInstance()> > {> > if> (single_instance ==> null> )> > single_instance => new> Singleton();> > return> single_instance;> > }> }> // Class 2> // Main class> class> GFG {> > // Main driver method> > public> static> void> main(String args[])> > {> > // Instantiating Singleton class with variable x> > Singleton x = Singleton.getInstance();> > // Instantiating Singleton class with variable y> > Singleton y = Singleton.getInstance();> > // Instantiating Singleton class with variable z> > Singleton z = Singleton.getInstance();> > // Printing the hash code for above variable as> > // declared> > System.out.println(> 'Hashcode of x is '> > + x.hashCode());> > System.out.println(> 'Hashcode of y is '> > + y.hashCode());> > System.out.println(> 'Hashcode of z is '> > + z.hashCode());> > // Condition check> > if> (x == y && y == z) {> > // Print statement> > System.out.println(> > 'Three objects point to the same memory location on the heap i.e, to the same object'> );> > }> > else> {> > // Print statement> > System.out.println(> > 'Three objects DO NOT point to the same memory location on the heap'> );> > }> > }> }> |
>
>Wyjście
Hashcode of x is 558638686 Hashcode of y is 558638686 Hashcode of z is 558638686 Three objects point to the same memory location on the heap i.e, to the same object>
Wyjaśnienie wyjścia:
W klasie singleton, kiedy po raz pierwszy wywołujemy metodę metodę getInstance(). , tworzy obiekt klasy o nazwie single_instance i zwraca go do zmiennej. Ponieważ single_instance jest statyczny, zmienia się z null na jakiś obiekt. Następnym razem, jeśli spróbujemy wywołać metodę getInstance(), ponieważ single_instance nie ma wartości null, zostanie ona zwrócona do zmiennej, zamiast ponownie tworzyć instancję klasy Singleton. Ta część jest wykonywana za pomocą warunku if.
W klasie głównej tworzymy instancję klasy singleton z 3 obiektami x, y i z, wywołując metodę statyczną metoda getInstance() . Ale w rzeczywistości po utworzeniu obiektu x zmienne y i z są kierowane na obiekt x, jak pokazano na diagramie. Zatem jeśli zmienimy zmienne obiektu x, znajdzie to odzwierciedlenie, gdy uzyskamy dostęp do zmiennych obiektów y i z. Również jeśli zmienimy zmienne obiektu z, znajdzie to odzwierciedlenie, gdy uzyskamy dostęp do zmiennych obiektów x i y.
Skończyliśmy omawianie wszystkich aspektów przykładu 1 i zaimplementowaliśmy to samo, teraz będziemy implementować klasę Singleton z nazwą metody taką samą jak nazwa klasy.
Przykład 2:
Jawa
// Java program implementing Singleton class> // with method name as that of class> // Class 1> // Helper class> class> Singleton {> > // Static variable single_instance of type Singleton> > private> static> Singleton single_instance => null> ;> > // Declaring a variable of type String> > public> String s;> > // Constructor of this class> > // Here private constructor is used to> > // restricted to this class itself> > private> Singleton()> > {> > s => 'Hello I am a string part of Singleton class'> ;> > }> > // Method> > // Static method to create instance of Singleton class> > public> static> Singleton Singleton()> > {> > // To ensure only one instance is created> > if> (single_instance ==> null> ) {> > single_instance => new> Singleton();> > }> > return> single_instance;> > }> }> // Class 2> // Main class> class> GFG {> > // Main driver method> > public> static> void> main(String args[])> > {> > // Instantiating Singleton class with variable x> > Singleton x = Singleton.Singleton();> > // Instantiating Singleton class with variable y> > Singleton y = Singleton.Singleton();> > // instantiating Singleton class with variable z> > Singleton z = Singleton.Singleton();> > // Now changing variable of instance x> > // via toUpperCase() method> > x.s = (x.s).toUpperCase();> > // Print and display commands> > System.out.println(> 'String from x is '> + x.s);> > System.out.println(> 'String from y is '> + y.s);> > System.out.println(> 'String from z is '> + z.s);> > System.out.println(> '
'> );> > // Now again changing variable of instance z> > z.s = (z.s).toLowerCase();> > System.out.println(> 'String from x is '> + x.s);> > System.out.println(> 'String from y is '> + y.s);> > System.out.println(> 'String from z is '> + z.s);> > }> }> |
>
numpy zera
>Wyjście
String from x is HELLO I AM A STRING PART OF SINGLETON CLASS String from y is HELLO I AM A STRING PART OF SINGLETON CLASS String from z is HELLO I AM A STRING PART OF SINGLETON CLASS String from x is hello i am a string part of singleton class String from y is hello i am a string part of singleton class String from z is hello i am a string part of singleton class>
Wyjaśnienie: W klasie singleton, gdy po raz pierwszy wywołujemy metodę Singleton(), tworzy ona obiekt klasy Singleton o nazwie single_instance i zwraca go do zmiennej. Ponieważ single_instance jest statyczny, zmienia się z null na jakiś obiekt. Jeśli następnym razem spróbujemy wywołać metodę Singleton(), ponieważ single_instance nie ma wartości null, zostanie ona zwrócona do zmiennej, zamiast ponownie tworzyć instancję klasy Singleton.
Przeczytaj dalej: Samouczek dotyczący wzorców projektowych w Javie