Singleton Simple instance design pattern analysis
Preface
Today I will give you a comprehensive summary of the most commonly used design pattern in Android development - singleton mode.
Regarding the introduction to design patterns, you can read what I wrote before: 1 minute to fully understand "design patterns"
Table of contents
1. Introduce
1.1 What problems are solved
As mentioned before, design pattern = a solution to a certain type of specific problem, so what problem is the singleton pattern ?
Meaning: Singleton = an instance;
Problem solved: Reduce the coupling between objects
Solution: Singleton pattern, that is, implementing that a class has only one instantiated object and provides a global access point
1.2 Instance introduction
Next I use an instance to introduce singleton pattern
Background: Xiaocheng has a plastics factory, but there is only one warehouse inside.
Purpose: I want to use code to implement warehouse management
Current practices: Establish warehouses and workers
Among them, the quantity in the warehouse class = the quantity of goods; workers have the handling methods MoveIn(int i) and MoveOut(int i).
Problems: Through testing, it was found that every time a worker moves, a new warehouse will be built, that is, the goods are not placed in the same warehouse. What's going on? (See the code below)
package scut.designmodel.SingletonPattern;//Warehouse class Class StoreHouse { private int quantity = 100; public void setQuantity(int quantity) { this.quantity = quantity; } public int getQuantity() { return quantity; }}//Walking human class Carrier{ public StoreHouse mStoreHouse; public Carrier(StoreHouse storeHouse){ mStoreHouse = storeHouse; } //Moving goods into the warehouse public void MoveIn(int i){ mStoreHouse.setQuantity(mStoreHouse.getQuantity()+i); } //Move out of the warehouse public void MoveOut(int i){ mStoreHouse.setQuantity(mStoreHouse.getQuantity()-i); }}//Worker handling test public class SinglePattern { public static void main(String[] args){ StoreHouse mStoreHouse1 = new StoreHouse(); StoreHouse mStoreHouse2 = new StoreHouse(); Carrier Carrier1 = new Carrier(mStoreHouse1); Carrier Carrier2 = new Carrier(mStoreHouse2); System.out.println("Are the two the same?"); if(mStoreHouse1.equals(mStoreHouse2)){// Use equals here instead of the == symbol, because the == symbol is just to compare the addresses of the two objects System.out.println("is the same"); }else { System.out.println("is not the same"); } //After the porter moves the goods, report the quantity of goods in the warehouse Carrier1.MoveIn(30); System.out.println("Warehouse product margin: "+Carrier1.mStoreHouse.getQuantity()); Carrier2.MoveOut(50); System.out.println("Warehouse product margin: "+Carrier2.mStoreHouse.getQuantity()); }}result:
Are the two the same? Product margin in the same warehouse: 130 Warehouse product margin: 50
2. Introduction to singleton pattern
2.1 Solved Problems (Application Scenarios)
Conflict: From the above results, it can be seen that the workers operated obviously not the same warehouse instance.
Goal: All workers operate the same warehouse instance
Singleton pattern is a solution to this type of problem: implement a class with only one instantiated object and provides a global access point 2.2 working principle
In Java, we operate these classes by using objects (after class instantiation). Class instantiation is performed through its constructor . If we want to implement that a class has only one instantiated object, we have to work on the constructor of the class:
General implementation of singleton mode: (including usage steps)
public class Singleton {//1. Create a private variable ourInstance (used to record a unique instance of Singleton) //2. Instantiate internally private static Singleton ourInstance = new Singleton();//3. Privatize the constructor of the class and prevent external calls to instantiate private Singleton() { }//4. Define a public method to provide a global unique access point for the class //5. Externally return a unique instance by calling the getInstance() method public static Singleton newInstance() { return ourInstance; }}OK, you should understand the introduction and principles of the singleton pattern, right? So let’s solve the problem that “the warehouse is not the same” that appeared above Xiaocheng!
2.3 Example introduction
Xiaocheng uses singleton mode to improve the code for the above example:
package scut.designmodel.SingletonPattern;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;//Singleton warehouse class StoreHouse { //The quantity of warehouse products private int quantity = 100; //Instantiate private static StoreHouse ourInstance = new StoreHouse();; //Let the external call the getInstance() method to return the unique instance. public static StoreHouse getInstance() { return ourInstance; } //Closed constructor private StoreHouse() { } public void setQuantity(int quantity) { this.quantity = quantity; } public int getQuantity() { return quantity; }}//Carrier man class Carrier{ public StoreHouse mStoreHouse; public Carrier(StoreHouse storeHouse){ mStoreHouse = storeHouse; } //Move goods into the warehouse public void MoveIn(int i){ mStoreHouse.setQuantity(mStoreHouse.getQuantity()+i); } //Move out of the warehouse public void MoveOut(int i){ mStoreHouse.setQuantity(mStoreHouse.getQuantity()-i); }}//Worker handling test public class SinglePattern { public static void main(String[] args){ StoreHouse mStoreHouse1 = StoreHouse.getInstance(); StoreHouse mStoreHouse2 = StoreHouse.getInstance(); Carrier Carrier1 = new Carrier(mStoreHouse1); Carrier Carrier2 = new Carrier(mStoreHouse2); System.out.println("Are the two the same?"); if(mStoreHouse1.equals(mStoreHouse2)){ System.out.println("is the same"); }else { System.out.println("not the same"); } //After the porter moves the goods, report the quantity of goods in the warehouse, Carrier1.MoveIn(30); System.out.println("Warehouse product margin: "+Carrier1.mStoreHouse.getQuantity()); Carrier2.MoveOut(50); System.out.println("Warehouse product margin: "+Carrier2.mStoreHouse.getQuantity()); }}result:
Are the two the same? It is the same warehouse commodity margin: 130 Warehouse commodity margin: 80
According to the results analysis, after using the singleton model, there is only one warehouse instance in the warehouse class, and there is no need to worry about porters entering the wrong warehouse! ! !
2.4 Advantages
2.5 Disadvantages
3. Implementation of singleton mode
3.1 General situation
Hungry style (the simplest singleton implementation method)
class Singleton { private static Singleton ourInstance = new Singleton(); private Singleton() { } public static Singleton newInstance() { return ourInstance; }}Application scenarios:
Lazy style
The biggest difference between lazy and hungry is the timing of the initialization operation of singletons :
class Singleton { private static Singleton ourInstance = null; private Singleton() { } public static Singleton newInstance() { if( ourInstance == null){ ourInstance = new Singleton(); } return ourInstance; }}Application scenarios:
3.2 Singleton mode implementation under multithreading
In the case of multithreading:
Solution 1: Synchronize Lock
Use synchronization lock synchronized (Singleton.class) to prevent multiple threads from entering simultaneously, causing instance to be instantiated multiple times.
class Singleton { private static Singleton ourInstance = null; private Singleton() { } public static Singleton newInstance() { synchronized (Singleton.class){ if( ourInstance == null){ ourInstance = new Singleton(); } } return ourInstance; }}Solution 2: Double check lock
A layer of if is added on the basis of the synchronization lock (except synchronized (Singleton.class) ) is to improve performance after the Instance has been instantiated and the next time it enters, it does not have to execute synchronized (Singleton.class) to obtain the object lock, thereby improving performance.
class Singleton { private static Singleton ourInstance = null; private Singleton() { } public static Singleton newInstance() { if( ourInstance == null){ synchronized (Singleton.class){ if( ourInstance == null){ ourInstance = new Singleton(); } } } return ourInstance; }}Solution 3: Static inner class
When the JVM class loads, the data is guaranteed to be synchronized. We use internal class implementation: create object instances in the internal class.
As long as the application does not use the internal class JVM, the singleton class will not be loaded, and the singleton object will not be created, thus achieving "lazy" lazy loading and thread safety.
class Singleton { //The singleton object will be created only when the inner class is loaded private static class Singleton2{ private static Singleton ourInstance = new Singleton(); } private Singleton() { } public static Singleton newInstance() { return Singleton2.ourInstance; }}Solution 4: Enumerate Types
The simplest and easy-to-use singleton implementation method (recommended by "Effective Java")
public enum Singleton{ //Define an enum element, which is an instance of Singleton instance; public void doSomething(){ } }How to use it is as follows:
Singleton singleton = Singleton.instance;singleton.doSomething();
5. Summary
This article mainly introduces the singleton model, including the principles and implementation methods. Next, I will continue to explain other design models. If you are interested, you can continue to pay attention to it.
Thank you for reading, I hope it can help you. Thank you for your support for this site!