This is my third article on getting Started.

define

Ensure that there is only one instance of a class, and instantiate it yourself and provide that instance to the entire system.

Usage scenarios

Ensure that a class has one and only one object to avoid creating multiple objects and unnecessary resource consumption. Or consider using singletons to create instance objects only once when creating an object to access IO, database, and other high resources.

advantages

  • Having only one instance in memory reduces memory overhead, especially for frequent occurrences of common and destroyed instances.
  • Overuse of resources can be avoided, as described in the appeal usage scenario.

disadvantages

  • Without interfaces, it is inconvenient to extend, and conflicts with the principle of simplicity, a class should only care about its internal logic, not how it is instantiated externally.

Code implementation

LanHanShi

The simplest implementation, the second method locks to avoid abnormal conditions in multithreaded situations, but it affects efficiency.

public class Singleton {
    private static Singleton instance;

    private Singleton(a) {}public static Singleton getInstance(a){
        if(Objects.isNull(instance)){
            instance = new Singleton();
        }
        return instance;
    }

    public static synchronized Singleton getInstances(a){
        if(Objects.isNull(instance)){
            instance = new Singleton();
        }
        returninstance; }}Copy the code

The hungry type

Without the lock, the execution efficiency is improved, but it is initialized when the class is loaded, and there is no memory waste to implement the pull load.

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

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

Double lock

The double lock is an optimization of the method level lock, which reduces the time to acquire some instances and satisfies the full load.

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton (a){}
    public static Singleton getSingleton(a) {
        if (Objects.isNull(singleton)) {
            synchronized (Singleton.class) {
                if (Objects.isNull(singleton)) {
                    singleton = newSingleton(); }}}returnsingleton; }}Copy the code

Enumeration type

The simplest way to do this is to use enumerations. Enumerations are the same as ordinary Java classes. They can have fields and methods. Most importantly, they are thread safe by default and are singletons in any case.

public enum Singleton {  
    INSTANCE;  
    public void doSomething(a) {}}Copy the code

Wrapper utility class

In the androd framework source code, we can wrap a layer of SingletonFactory. We can wrap all instances that need to use the singleton pattern in SingletonFactory to reduce code redundancy. I recommend this use

public abstract class SingletonUtils<T> {
    private T instance;

    public abstract T create(a);

    public final T getInstance(a){

        if(Objects.isNull(instance)){
            synchronized (this) {if(Objects.isNull(instance)) instance = create(); }}returninstance; }}Copy the code
public class SingletonFactory {

    public static A getA(a) {
        return new Singleton<A>() {
            @Override
            protected A create(a) {
                return new A();
            }
        }.getInstance();
    }

    public static B getB(a) {
        return new Singleton<B>() {
            @Override
            protected B create(a) {
                return new B();
            }
        }.getInstance();
    }

    public static SensorOrientation getC(a) {
        return new Singleton<C>() {
            @Override
            protected C create(a) {
                return newC(); } }.get(); }}Copy the code

Learning reference from “re-learn Java design pattern. PDF” “Android source design pattern analysis and actual combat”