Make writing a habit together! This is the third day of my participation in the “Gold Digging Day New Plan ยท April More text Challenge”. Click here for more details.

Model motivation

For some classes in the system, only one instance is important. For example, a system can have multiple printing tasks, but only one working task; A system can only have one window manager or file system…

How do you ensure that there is only one instance of a class that is easily accessed? Defining a global variable ensures that an object is always accessible, but does not prevent us from instantiating multiple objects.

A better solution is to make the class itself responsible for keeping its unique instance. This class guarantees that no other instances will be created, and it can provide a method to access that instance. This is the singleton pattern!

The singleton pattern solves both problems at once, so it violates the single responsibility principle:

  1. Ensure that there is only one instance of a class. Why would anyone want to control the number of instances a class has? The most common reason is to control access to some shared resources, such as databases or files. โญ Note: A normal constructor cannot implement a single instance because the constructor’s design dictates that it must always return a new object.
  2. Provide a global access node for the instance. Remember those global variables you used to store important objects? They are convenient to use, but very insecure, because any code can overwrite their content. Like global variables, the singleton pattern allows specific objects to be accessed from anywhere in the program, but it protects that instance from being overwritten by other code.

Today, the singleton pattern is so popular that people often refer to anything that solves only one of the problems described above as a singleton.

define

The singleton pattern is a creation pattern.

The singleton pattern ensures that a class has only one instance and that it instantiates and makes that instance available to the entire system. This class is called a singleton class, which provides globally accessible methods.

UML class diagrams

The model structure

โญ All implementations of singletons contain the same two steps:

  • Privatize the default constructorprivateTo prevent other objects from creating new objectsnew.
  • Create a new static build method as a constructor. This function “surreptitiously” calls the private constructor to create the object and store it in a static member variable. All subsequent calls to this function will return the cache object.

The singleton pattern contains the following roles:

  • SingletonThe: singleton class declares a class namedgetInstance()A static method that gets an instance to return an identical instance of its class. The constructor of a singleton must be on the clientClientTherefore, callgetInstance()Must be the only way to get a singleton pattern.

More instances

In an operating system, a print pool is an application used to manage print tasks. You can delete, suspend, or change the priority of print tasks by using the print pool. Only one print pool object is allowed to run in a system. Now the singleton pattern is used to simulate the design of print pool.

The sample code

public class Singleton {
    private static Singleton instance;

    private Singleton(a) {}public static Singleton getInstance(a) {
        if (instance == null) {
            instance = new Singleton();
        }
        returninstance; }}Copy the code

The advantages and disadvantages

โžค Provides controlled access to unique instances. Because the singleton class encapsulates its unique instance, it tightly controls how and when clients access it and provides shared concepts for design and development teams.

โžค Save resources because there is only one object in the system memory. Singletons can improve performance for those objects that need to be created and destroyed frequently.

โžค Allow a variable number of instances. We can modify the singleton pattern to obtain a specified number of object instances using a similar method to the singleton pattern.

โŒ Because the singleton pattern has no abstraction layer, it is difficult to extend the singleton class (in this case, extending the class rather than the pattern).

โŒ singleton classes are overloaded, acting as both a factory and a product; It solves two problems at once, violating the “single responsibility principle”.

โŒ Abuse of the singleton pattern will bring negative problems, such as the database connection pool object is designed as a singleton class in order to save resources, may lead to too many programs sharing the connection pool object and connection pool overflow; Many object-oriented languages (such as Java and C#) now provide automatic garbage collection, so if an instantiated object is not used for a long time, the system will consider it garbage, automatically destroy and recycle the resource, and the next time it is used, it will be instantiated again, which will cause the loss of the object state.

Applicable scenario

The singleton pattern is recommended when:

(1) The system only needs one instance.

(2) Only one common access point is allowed for a single instance of a client invoking class.

(3) The singleton pattern should only be used when only one instance of a class is required in a system. Conversely, if several instances of a class can coexist, the singleton pattern needs to be modified to become a multi-instance pattern.

The singleton pattern is implemented

(1) Java.lang.Runtime class

(2) A table with auto-numbered primary keys can be used by multiple users at the same time, but the generator of the primary key number is the same instance, so the last numbered primary key ID can be used, otherwise there will be primary key duplication, so it can be implemented through singleton mode.

(3) By default, Spring creates bean instances using the singleton pattern:

<bean id="date" class="java.util.Date" scope="singleton"/>
Copy the code

Model extension

As the singleton pattern described above applies only to single threads, let’s consider what might happen if multiple threads were introduced.

Hunchman singleton pattern

A hanchian singleton class instantiates itself when it is loaded. In terms of resource utilization efficiency alone, this is slightly worse than the lazy singleton class. In terms of speed and reaction time, it is slightly better than the lazy singleton class.

public class EagerSingleton {
    private static EagerSingleton instance = new EagerSingleton();

    private EagerSingleton(a) {}public static EagerSingleton getInstance(a) {
        returninstance; }}Copy the code

Lazy singleton pattern

Lazy singleton classes are instantiated the first time a resource is used. Some resource initialization may take a lot of time, and lazy loading can improve resource utilization efficiency. One significant problem with the lazy singleton pattern, however, is that you have to deal with the problems that can arise from multithreading. When multiple threads reference such static methods for the first time, it is likely that multiple instances will be initialized at the same time, and threads must be synchronized when objects are first instantiated.

public class LazySingleton {
    private static LazySingleton instance = null;

    private LazySingleton(a) {}private static LazySingleton getInstance(a) {
        if (instance == null) {
            // Use thread locking mechanism
            synchronized (LazySingleton.class) {
                if (instance == null) {
                    instance = newLazySingleton(); }}}returninstance; }}Copy the code

Lazy multi-example pattern

The idea of singleton pattern is used to realize multi-instance pattern to ensure that only a limited number of objects of a class can exist in the system.

public class LazyMultiInstance {
    private static LazyMultiInstance instance = null;
    // Used to record the number of current instantiated objects
    private static volatile Integer count = 0;

    private LazyMultiInstance(a) {}public static LazyMultiInstance getInstance(a) {
        // Ensure that the system has at most three objects of this class
        if (LazyMultiInstance.count < 3) {
            synchronized (LazyMultiInstance.class) {
                if (LazyMultiInstance.count < 3) {
                    instance = newLazyMultiInstance(); }}}returninstance; }}Copy the code

The last

๐Ÿ‘† previous article: “Design Pattern” ๐ŸŒ“ Prototype pattern (Prototype)

๐Ÿ‘‡ Next article: Continuing article, please look forward to…

โค๏ธ Good code without explanation, pay attention to the “rip design patterns” column, with me to learn design patterns, your code can be as elegant as poetry!

โค๏ธ / END/If this article is helpful to you, click a “like” to support it, your support is my biggest motivation!