单例模式

Posted by Think different. on February 17, 2020

1.单例模式(Singleton)

1.什么是单例模式

单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式

2.要点

1.一个类只能有一个实例

构造器私有化

2.它必须自行创建这个实例

含有一个该类的静态变量来保存这个唯一的实例

3.它必须自行向整个系统提供这个实例

对外提供获取该实例对象的方式:

1)直接暴露

2)用静态变量的get方法获取

3.几种常见形式

1.饿汉式:

在类初始化时直接创建对象,不存在线程安全问题

1.直接实例化饿汉式(简洁直观)

/**
 * 饿汉式:
 *     直接创建实例对象,不管是否需要这个对象都会创建,类加载时自动创建
 *
 * (1)构造器私有化
 * (2)自行创建,并且用静态变量保存
 * (3)向外提供这个实例-public
 * (4)强调这是一个单例-final
 */
public class SingletonDemo1 {
    public static final SingletonDemo1 INSTANCE = new SingletonDemo1();
    private SingletonDemo1(){

    }
}

2.枚举式(最简洁)

/**
 * 枚举类型,表示该类型的对象是有限的几个
 * 我们可以限定为一个,就成了单例
 */
public enum SingletonDemo2 {
    INSTANCE
}

3.静态代码块饿汉式(适合复杂实例化)

/**
 * 如果这个类需要初始化变量等操作,可能会需要用到这种方式,把需要初始化的变量等在静态代码块中进行初始化。
 */
public class SingletonDemo3 {
    public static final SingletonDemo3 INSTANCE;

    static{
        INSTANCE = new SingletonDemo3();
    }

    private SingletonDemo3(){}
}

2.懒汉式:

延迟创建对象

1.线程不安全(适用于单线程)

/**
 * 懒汉式:延迟创建这个对象
 *  (1)构造器私有化
 * (2)用一个静态变量保存这个唯一的实例
 * (3)提供一个静态方法,获取这个实例对象
 */
public class SingletonDemo4 {
    private static SingletonDemo4 instance;
    private SingletonDemo4 (){}
    public static SingletonDemo4 getInstance() {
        if (instance == null) {
            instance = new SingletonDemo4();
        }
        return instance;
    }
}

2.线程安全(适用于多线程:加锁)

public class SingletonDemo5 {
    private static SingletonDemo5 instance;
    private SingletonDemo5(){}
    public static SingletonDemo5 getInstance() {
        if (instance == null) {
            synchronized (SingletonDemo5.class) {
                if (instance == null) {
                    instance = new SingletonDemo5();
                }
            }
        }
        return instance;
    }
}

3. 静态内部类形式(适用于多线程)

/**
 * 在内部类被加载和初始化时,才创建INSTANCE实例对象
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,而是要单独去加载和初始化的
 * 因为是在内部类加载和初始化时创建的,因此是线程安全的
 */
public class SingletonDemo6 {
    private SingletonDemo6(){}

    private static class Inner{
        private static final SingletonDemo6 INSTANCE = new SingletonDemo6();
    }

    public static SingletonDemo6 getInstance(){
        return Inner.INSTANCE;
    }
}

4.总结

1.如果是饿汉式,枚举形式最简单

2.如果是懒汉式,静态内部类形式最简单