zoukankan      html  css  js  c++  java
  • 设计模式之 单例模式

      单例模式作为一种目标明确、结构简单、理解容易的设计模式,在软件开发中使用频率相当高,在很多应用软件和框架中都得以广泛应用。

    有什么用?

      有的时候,对于一些对象,我们只需要一个或者说“唯一”,比方说:任务管理器、线程池、缓存、对话框、偏好设置和注册表的对象,日志对象,充当打印机、显卡等设备的驱动程序的对象。事实上,这类对象只能有一个实例,如果制造出多个实例,就会导致许多问题产生,例如:程序出错、资源使用过量、或者是得到不一致的结果。

      虽然很多时候,通过程序员之间做的约束、或者是利用全局变量(Java的静态变量),的确可以保证一个类只存在一个实例。但那样做不一定是最好的,我们需要一个更好的、通用的解决方案。而经过时间的考验,单件模式 可以确保一个对象只有一个实例被创建。单件模式也给了我们一个全局的访问点,和全局变量一样方便,又没有全局变量的缺点。

      全局变量的缺点,举例来说,如果将对象赋值给一个全局变量,那么你必须在程序一开始就创建好对象,若这个对象非常的耗费资源,而程序在这次的执行过程中又一直没用到它,不就形成浪费了吗?而利用单例模式,我们可以在需要的时候才创建对象。

      其实利用静态类变量、静态方法和适当的访问修饰符,的确也可以做到这一点。但是不管使用哪一种方法,我们都应该了解单例模式的运作方式和具体使用。

    单例模式的实现可分为四大类:

      第一类,饿汉式(空间换时间)

    最简单的实现方式

    public class Singleton {  
        private static Singleton instance = new Singleton();  
        private Singleton (){}  
        public static Singleton getInstance() {  
            return instance;  
        }  
    }

      第二类,懒汉式(时间换空间)

     线程不安全

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

    线程安全

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

    双检锁/双重校验锁(DCL,即 double-checked locking)

    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;  
        }  
    }

    通过volatile关键字防止指令重排序。

    volatile关键字不但可以保证线程访问的变量值是主存中的最新值,而且可以防止指令重排。(非最佳实现,据说大部分JVM的implementation并不尊重volatile的规则,并且这个类可以通过反射构造多个实例对象。)

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

      第三类,IoDH(initialization on demand holder) 

    也可称静态内部类方式,延迟加载且线程安全(任何初始化失败都会导致单例类不可用,也就是说,IoDH这种实现方式只能用于能保证初始化不会失败的情况。)

    加载一个类时,其内部类不会同时被加载。一个类被加载,当且仅当其某个静态成员(静态域、构造器、静态方法等)被调用时发生。

    需要延迟加载时,推荐使用

    public class Singleton {  
        private Singleton (){}  
    
        private static class SingletonHolder {  
            private static final Singleton INSTANCE = new Singleton();  
        }  
        
        public static final Singleton getInstance() {  
            return SingletonHolder.INSTANCE;  
        }  
    }

      第四类,枚举

    这种实现方式还没有被广泛采用,由于该方式的单例在面对复杂序列化以及反射攻击时,都能防止多次实例化,被称为单例模式的最佳实现。

    不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。不能通过 reflection attack 来调用私有构造方法。

    public enum SingletonEnum {
          INSTANCE;
          public void doSomething() {
          }
      }

    总结

    • 一个核心原理就是私有构造,并且通过静态方法获取一个实例。
    • 在这个过程中必须保证线程的安全性。
    • 推荐用静态内部内实现单例,或加了Volatile关键字的双重检查单例(JDK 1.5及以上版本)

    参考:

      总结单例模式的几种实现方式及优缺点

      单例模式-菜鸟教程

    共同学习,共同进步,若有补充,欢迎指出,谢谢!

  • 相关阅读:
    A Survey of Machine Learning Techniques Applied to Software Defined Networking (SDN): Research Issues and Challenges
    A Deep Learning Based DDoS Detection System in Software-Defined Networking (SDN)
    解决win10 USB转串口无法使用
    Feeder-Link Outage Prediction Algorithms for SDN-based High-Throughput Satellite
    Flow monitoring in Software-Defined Networks
    Refining Network Intents for Self-Driving Networks
    2020生活变化
    【转载】 图解最小堆形成-以数组方式表示
    福大软工 · 最终作业
    福大软工 · 第十二次作业
  • 原文地址:https://www.cnblogs.com/dengguangxue/p/11393654.html
Copyright © 2011-2022 走看看