• Singleton Pattern(单例模式)


    1、简介

      单例模式,顾名思义,即在整个系统中,类的实例对象只有一个。

      单例模式具有以下特点:

      • 单例类只能有一个实例
      • 单例类必须自己创建自己的唯一实例
      • 单例类必须给所有其他对象提供这一实例

    2、实现

      其实现原理为将构造函数设为private,以让外部无法使用new来实例化对象。单例类内部保存着一个该类的静态实例对象并对外提供。

      2.1 饿汉式

         饿汉式,所谓的“饿”是指一开始就要“吃”,即单例类一被加载就初始化。实现代码如下:

    public class Singleton1 {
        private static final Singleton1 instance = new Singleton1();
    
        private Singleton1() {}
        
        public static Singleton1 getSingleton() {
            return instance;
        }
    }

      2.2 懒汉式

      懒汉式,同饿汉式相反,所谓的“懒”指单例类被加载时未被初始化,等到被第一次获取单例对象时才对对象进行初始化。实现了懒加载。实现代码如下:

    public class Singleton2 {
        private static Singleton2 instance;
    
        private Singleton2() {}
    
        public static Singleton2 getSingleton() {
            if (instance == null)
                instance = new Singleton2();
            return instance;
        }
    }

      这种写法是线程不安全的(线程1运行到if之后阻塞,线程2对instance初始化完成,线程1将再次对instance进行初始化),在多线程环境下将不能正常工作。对其getSingleton()方法加锁以解决线程不安全问题,如下:

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

      以上写法属于线程安全型,但是它效率并不高。在instance被初始化之后,使用getSingleton获取对象,该方法仍然是加锁的,导致效率低下。对其进行修改,当instance为null的时候才对方法内部代码进行加锁。不为null时直接返回instance。如下:

    public class Singleton4 {
        private static Singleton4 instance;
        
        private Singleton4() {}
        
        public static Singleton4 getSingleton() {
            if (instance == null)
                synchronized(Singleton4.class){
                    if (instance == null)
                        instance = new Singleton4();
                }
            return instance;
        }
    }

      2.3 静态内部类

    public class Singleton5 {
        private static class InstanceClass {
            private static Singleton5 instance = new Singleton5();
        }
        
        private Singleton5() {}
        
        public static Singleton5 getSingleton() {
            return InstanceClass.instance;
        }
    }

    3、使用场景

      在一个系统中,要求一个类有且只有一个对象时可采用单例模式。例如

    • Java的Runtime对象
    • 要求生成唯一序列号的环境

    4、优点

    • 类只有一个实例,从而减小对内存的开销。特别是一个对象需要频繁地创建和销毁时。
    • 由于单例模式只生成一个实例,所以减少了系统的性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后用永久驻留内存的方式来解决。
    • 避免了对资源的多重利用。例如写文件,因为只有一个对象,从而避免了对同一个资源文件的同时写操作。
    • 可以在系统设置全局的访问点,优化和共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理。

    5、缺点

    • 单例模式一般没有接口,扩展很困难。
    • 对测试是不利的。在并行开发环境中,如果单例模式没有完成,是不能进行测试的,没有借口也不能使用mock的方式虚拟一个对象。
    • 单例模式与单一职责有冲突。一个类应该只实现一个逻辑,而不关心他是否是单例的,是不是单例取决于环境,单例模式把“要单例”和业务逻辑融合在一个类中。
  • 相关阅读:
    2012搜狗校园招聘笔试题(2)
    T-SQL中只截取日期的日期部分和日期的时间部分
    Delphi XE4 TStringHelper用法详解
    TScreen 类
    TScreen 类
    Delphi中Form的position属性与代码自定义窗体位置
    如何让窗口显示在电脑屏幕中间
    C#中整型数据类型
    C# WinForm开发系列
    SQL中EXCEPT和Not in的区别?
  • 原文地址:https://www.cnblogs.com/loading4/p/5654591.html
Copyright © 2020-2023  润新知