This article is aimed at those who first encountered the concept of patterns, heard about
Singleton
'e, or somehow made it, but did not understand anything. Welcome! For the first time, CodeGym students encounter patterns at level 15, when, in an unexpected way, the cap asks to “fix” and implement the pattern
Singleton
with lazy implementation. Students who have heard about for the first time
Singleton
instantly have a lot of questions: what is a pattern in general, why is it needed, what else
Singleton
, and finally, what else is a lazy implementation. Let's start answering in order:
What is a pattern anyway?
To answer this question for a better understanding, I think it's worth it from history. Among the programmers there is such a famous four authors: Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, who came up with an interesting idea.
They noticed that when writing programs, they often have to solve approximately the same tasks, and write code of the same type in structure. Therefore, they decided to describe in the form of patterns the typical patterns that often have to be used in object-oriented programming. The book was published in 1995 under the title
"Techniques of object-oriented design. Design Patterns" . The title of the book turned out to be too long and it was simply referred to as
The Book of the Gang of Four . In the first edition, 23 patterns were published, after which dozens of others were discovered. So, answering the question of this paragraph -
"What are patterns" , let's summarize in just a few words:
A pattern is a standardized solution to a common problem. |
And
Singleton
this is just one of those patterns.
Why do we need patterns (design patterns)
Programming is possible even without knowledge of patterns, you can be convinced of this simply by realizing the fact that by the 15th level on CodeGym you have written hundreds of mini-programs without knowing anything about their existence. This suggests that the pattern is a kind of tool, the presence of which distinguishes the master from the amateur:
Patterns describe how to correctly solve one of the typical tasks. As a consequence, knowing patterns saves you time. An analogy can be made with algorithms. For example, you can come up with "your" sorting algorithm
with blackjack and numbersand spend a lot of time on it, or you can use the one already described and implement it. It's the same with patterns. Plus, with the use of patterns, the code becomes more standardized, and when using the right patterns, you will be less likely to make mistakes, since they have long been foreseen and eliminated in this pattern. Well, plus everything, knowledge of patterns allows programmers to better understand each other. Simply saying the name of the template is enough, instead of trying to explain to your fellow programmers what you want from them.
So, to summarize, design patterns help:
- do not reinvent the wheel, but use standard solutions;
- standardize code;
- standardize terminology;
|
In conclusion of this section, we note that the entire variety of patterns can be divided into three large groups:
Finally the Singleton Pattern
Singleton
refers to
generative patterns . Its literal translation is loner. This pattern ensures that a class has only one object (one instance of the class) and a global access point is provided to that object. It should be clear from the description that this pattern should be applied in two cases:
- when no more than one object of any class should be created in your program. For example, in a computer game you have a "Character" class, and this class should have only one object describing the character itself.
- when it is required to provide a global access point to a class object. In other words, you need to make sure that the object is called from anywhere in the program. And, alas, for this it is not enough to simply create a global variable, because it is not write-protected and anyone can change the value of this variable and the global access point to the object will be lost. These
Singleton
'a properties are needed, for example, when you have a class object that works with a database, and you need the database to be accessed from different parts of the program. And Singleton
will ensure that no other code has replaced the previously created instance of the class.
These two tasks are solved by
Singleton
: the object in the program must be one and there is global access to it. In the example at level 15, the cap asks to implement this pattern for the following task (here is its description):
After carefully reading the condition, it becomes clear why exactly
Singleton
(Singleton) is needed here. After all, the program asks to create one object of each class:
Sun
,
Moon
,
Earth
. And it is logical to assume that each class in the program should create no more than one Sun / Moon / Earth, otherwise it will be absurd, unless of course you write your own version of star wars.
Three Step Java FeaturesSingleton
Singleton behavior in Java cannot be implemented with a normal constructor, because a constructor always returns a new object. Therefore, all implementations
Singleton
'a come down to hiding the constructor and creating a public static method that will manage the existence of a single object and "destroy" all newly-appearing objects. In the case of a call to
Singleton
'a, it must either create a new object (if it is not already in the program), or return an already created one. For this:
#1. – You need to add a private static field containing a single object to the class:
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
}
#2. - Make the class constructor (default constructor) private (so that access to it is closed outside the class, then it will not be able to return new objects):
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){}
}
#3 . – Declare a static creation method that will be used to get the singleton:
public class LazyInitializedSingleton {
private static LazyInitializedSingleton instance;
private LazyInitializedSingleton(){}
public static LazyInitializedSingleton getInstance(){
if(instance == null){
instance = new LazyInitializedSingleton();
}
return instance;
}
}
The above example is somewhat clumsy, because we simply hide the constructor and provide our own method instead of the standard constructor. Since this article is aimed at ensuring that CodeGym students can get in touch with this pattern (and patterns in general) for the first time, the implementation details of more complex Singletons will not be presented here. We only note that, depending on the complexity of the program, a more detailed refinement of this pattern may be required. For example, in a multi-threaded environment (see the topic Threads), several different threads can simultaneously call the Singleton getter, and the code described above will stop working, because each individual thread can create several instances of the class at once. Therefore, there are still several different approaches to creating the right Thread-safe singletons. But that's another story =)
And finally. What is the Lazy Initialization Cap Asked for Lazy Initialization is also called lazy initialization. This is a technique in programming when a resource-intensive operation (and creating an object is a resource-intensive operation) is performed on demand, and not in advance. Which is basically what happens in our
Singleton
'a. In other words, our object is created the moment it is accessed, not beforehand. It should not be assumed that the concept of lazy initialization is somehow strictly connected with
Singleton
'th. Lazy initialization is also used in other generative design patterns, such as Proxy (Deputy) and Factory Method (Factory method), but that's another story too =)
In preparing the materials of the article, the following sources were used:
- Java Singleton Design Pattern Best Practices with Examples
- Design patterns
- Proper Singleton in Java
GO TO FULL VERSION