单例模式的应用场景

  • 整个程序的运行中只允许有一个类的实例;
  • 需要频繁实例化然后销毁的对象。
  • 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  • 方便资源相互通信的环境

在项目中的具体使用目的

  • 封装一些常用的工具类,保证整个应用常用的数据统一
  • 保存一些共享数据在内存中,其他类随时可以读取。

单例模式的实现步骤

  • 构造方法必须进行私有化
  • 实例必须是一个且唯一,并且必须加上static属性
  • 对外提供获取该类对象的共有方法也是static属性

饿汉式(在程序创建的时候就进行初始化,并且对象唯一)

/**
 * 饿汉式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用!
 * 唯一缺点:不管用到与否,类装载时就完成实例化
 * Class.forName("")
 */
public class Singleton {
  
    private static Singleton singleton = new Singleton();
    
    //单例模式的特点,构造必须私有
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        return singleton;
    }
}
// 跟上面效果一样
public class Singleton {
  
    private static Singleton singleton;
  
    static {
        singleton = new Singleton();
    }
  
    //构造必须私有
    private Singleton() {
    }
    
    public static Singleton getInstance() {
        return singleton;
    }
}

懒汉式(使用了延迟加载来保证对象在没有使用之前,是不会进行初始化的)

// 加Synchronized的简单粗暴的方法
// 同步的代价必然会一定程度的使程序的并发度降低。
public final class Singleton {

    private static Singleton singObj = null;
    private Singleton() {
    }

    public static Synchronized Singleton getInstance() {
        if (null == singObj ) {
            singObj = new Singleton();
        }
        return singObj;
    }
}
// 双重检查锁(Double-Checked Lock)。
// 想办法把同步的粒度降低,只在初始化对象的时候进行同步。
public final class Singleton {

    private volatile static Singleton singObj = null;

    private Singleton() {
    }

    public static Singleton getInstance() {
        if (null == singObj ) {
            synchronized(Singleton.class) {
                if (null == singObj) {
                    singObj = new Singleton();
                }
            }
        }
        return singObj;
    }
}
// 静态内部类,完全使用了Java虚拟机的机制进行同步保证,没有任何同步关键字。
public class Singleton {
    private static class SingletonHolder {
        public final static Singleton instance = new Singleton();
    }
    
     private Singleton() {
     }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}
// 需要使用单例时,Singleton.INSTANCE即可得到枚举对象。
// 调用对象的方法,Singleton.INSTANCE.hello(),以实现需要的功能。
public enum Singleton {
    INSTANCE;   

    // all the methods you want
    private String hello() {
        System.out.println("Hello, world!");
    }
}

23种设计模式