Singleton mode of software design

When programming, no matter you write your own code or look at other people's code, you often encounter a design mode called singleton. The problem to be solved by this mode is to provide a global and unique instance object in a system. Listening to a tongue twister sentence, I use a diagram to illustrate:

As shown in the figure above, let's make a hypothesis:

  1. Compare the universe to a software system;

  2. Compare the stars in the universe to different objects in the system;

  3. Compare humans to callers (users) who want to call / use these objects in the system;

At this time, from the perspective of users, the earth object here is the only object in the overall situation. Whether Zhang San, Li Si or Wang Wu calls the resources on the earth (water resources, coal resources, etc.), they have to call the earth object. No matter who of them gets the same object every time, no one can get a unique earth to enjoy its resources, Therefore, the earth object is shared, open, global and unique to everyone in the system of the universe. This is the scenario of singleton use.

In actual software development, the singleton model is often used to build a global and unique shared instance. You might as well put aside the curse of design model and think about what the so-called singleton model looks like. Through the relationship between the universe, the earth and human beings in the above figure, what we want to build now is an object like the earth, and the problem becomes: how to ensure that the earth object we build is global Unique and shared?

Let's create a class like Earth first. We can ignore the resources and other elements existing on the earth. Here we will take Java as an example, but it should be noted that the singleton mode is not related to the language:

/**
The planet is in its infancy. There is no grass. It's not urgent. Let's take our time
*/
public class Earth {

}

We have built a class of earth, which meets the global and shared characteristics. Anyone can call it, as long as it can be done through the following code:

Earch earch = new Earch();

So how to guarantee the uniqueness, because we know that if three people call the above 👆 This line of code will generate three different objects, so the uniqueness of the Earth does not exist. Therefore, to solve the problem of uniqueness, we have to talk about the concept of constructor. Constructor is an initialization function automatically called when new an object. Although it does not display and declare this constructor when creating Earth class, it implicitly brings a default constructor, As follows:

/**
The planet is in its infancy. There is no grass. It's not urgent. Let's take our time
 */
public class Earth {
    // Hello, I'm the constructor
    public Earth(){
       System.out.println("Constructor“);
    }
}

So when we initialize the object: new Earth(), the constructor will be printed out for a small test 👇:

/**
The planet is in its infancy. There is no grass. It's not urgent. Let's take our time
 */
public class Earth {
    // Hello, I'm the constructor
    public Earth(){
       System.out.println("Constructor“);
    }
}

public class SingletonTest{
    public static void main(String[] args) {
        new Earth();
    }
}

result 👇 We can see that this line is printed out, and we just new it in other classes:

Then, let's go back to the issue of uniqueness. We can boldly guess that to be unique, we must have autonomy. Earth needs to control who creates the right. Not everyone can create it, so we must make a convergence on the right of object creation 👇:

/**
The planet has just been formed. There is no grass. It's not urgent. Let's take our time
 */
public class Earth {
    // I'm the constructor, but I don't give it to anyone
    private Earth(){
       System.out.println("Constructor“);
    }
}

The way of convergence is to change the public in front of the constructor to private, which is a permission convergence. Originally, public access has become private access. At this time, let's try new again 👇:

public class SingletonTest{
    public static void main(String[] args) {
        new Earth();
    }
}

As a result, an error was reported when compiling, because the private method in Earth cannot be accessed:

Here, our permission convergence strategy has been basically implemented successfully, and external classes can no longer call Earth. As long as the Earth class can create itself and provide external access, the purpose of object uniqueness can be achieved;

public class Earth {

    private static Earth earth = new Earth();

    private Earth(){
        System.out.println("Constructor");
    }
    
    public static Earth getInstance(){
        return earth;
    }
}

We are in the earth class 👆 It creates an object and provides a public access method getInstance to call the outside world. In this way, the principle of global, shared and unique is achieved. Finally, we use multithreading to simulate multiple users and test it 👇 Whether all users get the same object.

public class SingletonTest{
    public static void main(String[] args) {

        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                //Print the address of the object to see if everyone has obtained the same object
                System.out.println(Earth.getInstance());
            }
        };

        Thread thread1 = new Thread(runnable);
        Thread thread2 = new Thread(runnable);
        Thread thread3 = new Thread(runnable);
        Thread thread4 = new Thread(runnable);
        Thread thread5 = new Thread(runnable);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();

    }
}

The result is in line with the expectation. In this way, we have constructed the most basic and simplest single example. Later, we will continue to discuss some other interesting things on the earth 🤔.  

Tags: Java Singleton pattern

Posted by meomike2000 on Sun, 15 May 2022 01:14:14 +0300