【设计模式】单例模式

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 与数据库的连接等。

posted @ 2020-09-18 10:35  ShinyRou  阅读(123)  评论(0编辑  收藏  举报