美文网首页
单例模式的实现方式

单例模式的实现方式

作者: 技术客栈 | 来源:发表于2020-07-22 15:47 被阅读0次

    单例模式介绍

    单例模式是我们最常用使用最广泛的模式之一。在很多的应用场景下为了避免多次重复创建对象如:网络请求、缓存、数据库操作等都是很消耗资源的。因此在使用这个模式时,单例对象类必须保证只有一个实例存在。

    单例的定义

    确保某个类只有一个实例化对象。

    单例的使用场景

    单例设计的目的是保证某个类的实例只有一份。重复创建对象是会产生资源的消耗。向具体的网络请求、数据库操作、IO操作就可以考虑使用该模式。

    单例的实现方式

    1. 懒汉模式
      懒汉模式在第一次调用 getInstace() 时进行初始化。相对应也为该方法加上了synchronized 关键字,处理在多线程情况下保证单例对象的唯一性。
    public class Singleton {
        private static Singleton instance;
        
        private Singleton() {
        }
        public static synchronized Singleton getInstace() {
            if (instance == null){
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    优点:只有在使用的时候才会被实例化,节约资源。
    缺点:首次加载需要实例化,反应稍慢。每次调用 getInstance() 都需要进行同步,造成不必要的同步开销,一般不建议使用。

    1. 双重校验(DCL) 模式
      该模式既能保证在使用的时候获取实例,又能保证线程安全,并且单例对象初始化之后使用getInstance不在进行不必要的同步开销。
    public class Singleton {
        private volatile static Singleton instance;
    
        private Singleton() {
        }
        public static synchronized Singleton getInstace() {
            if (instance == null){
                synchronized (Singleton.class){
                    if (instance == null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    该首先会经过如下几步:

    • 为该单例分配内存
    • 调用构造函数,初始化成员字段
    • 将 instance 指向分配的内存空间
      在JDK 1.5 之后调整了JVM,使用了关键字volatile ,将instance 对象直接定义为 private volatile static Singleton instance, 可以保证获取对象每次从主内存中读取,当然volatile 在一定程度上会影响性能,但为保证程序的正确性,在一些性能上可以忽略。
      优点:首次执行getInstance 才会被实例化,效率高。资源利用率高。
      缺点:首次加载稍慢,由于Java 内存模型原因偶尔会失败。
    1. 静态内部类模式
      提倡使用该方式既能保证线程的同步,又能保证对象的唯一性。同时有延迟了类的实例化。
    public class Singleton {
    
        private Singleton() {
        }
        public static synchronized Singleton getInstace() {
            
            return SingletonHodler.instance;
        }
        private static class SingletonHodler{
            private static final Singleton instance = new Singleton();
        }
    }
    

    优点:第一次加载 Singleton 时,不会初始化 instance,在执行Singleton getInstance 方法时instance才会被实例化。

    1. 枚举模式
      默认枚举创建的实例都是线程安全的。而且任何情况下都是一个实例化对象。
    public enum  Singleton {
        
        INSTANCE;
    
       public void printInfo(){
           System.out.println("日志信息输出");
       }
    }
    

    优点:写法简单,既能保证线程同步又能保证对象的唯一性。

    1. 容器模式
      通过使用HashMap 容器的形式将多种单例进行统一管理,在使用时通过key 获取对应的实例化对象降低耦合度,隐藏内部实现。
    public class  Singleton {
        
        private static HashMap<String,Object> hashMap = new HashMap<>();
    
        private Singleton() {
        }
       
        public static void register(String key,Object instance){
            if (isKeyEmpty(key)) {
                return;
            }
            if (hashMap == null){
                hashMap = new HashMap<>();
            }
            
            if (!hashMap.containsKey(key)){
                hashMap.put(key,instance);
            }
        }
       
        public static Object getInstace(String key){
            if (hashMap == null){
                return null;
            }
            if (isKeyEmpty(key)) {
                return null;
            }
            
            return hashMap.get(key);
        }
        public static boolean isKeyEmpty(String key){
            if (key == null || "".equals(key)){
                return true;
            }
            return false;
        }
    }
    

    经过上面的几种单例模式介绍,推荐使用静态内部类模式实现的单例模式。具体的使用还是视情况而定。从而在保证唯一性的情况下还能保证线程同步,达到节约资源的目的。

    相关文章

      网友评论

          本文标题:单例模式的实现方式

          本文链接:https://www.haomeiwen.com/subject/koqfphtx.html