【设计模式】单例模式
1.什么是单例模式
单例模式是一种创建型设计模式, 让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
理论上类的属性都是外部不可访问的,不然所有操作这个对象的都可以进行修改就违背了初衷。
2.单例模式的几种实现
2.1 饿汉式
public class SingleObject {
private String ob1;//属性不对外开放
//创建 SingleObject 的一个对象
private static SingleObject instance = new SingleObject();
//让构造函数为 private,这样该类就不会被实例化
private SingleObject(){}
//获取唯一可用的对象
public static SingleObject getInstance(){
return instance;
}
饿汉式 是直接初始化了一个对象,不存在线程安全问题,但是类加载时就初始化,浪费内存。
2.2 懒汉式(线程安全)
public class Singleton {
private static volatile Singleton instance;
private Singleton (){}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
在需要使用时,再初始化对象,如果已经初始化则直接返回该对象
线程安全,不使用synchronized 关键字存在线程安全问题,多个线程同时getInstance 可能创建了多个对象。
缺点:所有的操作都加了锁,性能较差
2.3双重校验锁
public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
2.4 使用静态内部类
public class Singleton {
private static class SingletonInner {
private static Singleton singleton = new Singleton();
}
private Singleton (){}
public static Singleton getSingleton(){
return SingletonInner.singleton;
}
}
静态内部类初始化是在SingletonInner类初始化时触发的,并且由于静态内部类只会被加载一次,所以这种写法也是线程安全的。
2.5 使用枚举实现单例
上述各种实现都存在两个问题
1.使用反射创建对象
2.通过反序列化创建对象
使用枚举实现单例可以天然的解决这两个问题
参看:https://blog.csdn.net/javazejian/article/details/71333103
3.单例模式的应用场景
如果程序中的某个类对于所有客户端只有一个可用的实例, 可以使用单例模式。
如果你需要更加严格地控制全局变量, 可以使用单例模式。
1、要求生产唯一序列号。
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。