设计模式之单例模式学习笔记

作者: smileNicky | 来源:发表于2018-04-20 15:31 被阅读14次

    前言

    本博客介绍一种创建型模式:单例模式
    这是一种比较容易理解的设计模式,可以理解为创建对象的一种很好的做法。可以尽量避免创建过多的对象,给JVM造成很大的负载。

    应用场景

    单例模式的一些应用场景:
    1、比如数据连接类,这是需要经常调用的
    2、网站访问量统计的服务类,需要多次调用
    3、导出导入Excel表,一些业务复杂的系统需要多次调用
    ...

    总结起来就是需要经常调用的通用类,我们可以用单例模式进行很好的设计。

    编程思想

    单例模式涉及了两种重要的编程思想:懒加载思想和缓存思想

    缓存思想:

        private static Singleton instance = null;//先放内存缓存
       
        public static Singleton getInstance() {
            if (instance == null) {//内存加载不到,创建对象
                instance = new Singleton();
            }
            return instance;//内存缓存有,直接调用
        }
    

    懒加载思想:
    下面例子就是懒加载的简单应用,创建一个对象都是需要用的时候实例,尽量不要在加载类的时候就实例了,这种方法可以很好的避免给JVM增加负载。这是一种很好的编程习惯。

    public static Singleton getInstance() {
            if (instance == null) {//对象需要用时才实例
                instance = new Singleton();
            }
            return instance;
        }
    

    单例模式实例

    下面介绍几种常用的单例模式实例

    1、懒汉模式
    这是一种线程不安全,懒加载的方式

    public class Singleton {
        private static Singleton instance;
        //定义private构造函数,使类不可以被实例
        private Singleton (){}
    
        /**
         * 懒汉模式,线程不安全,懒加载
         * @return
         */
        public static Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    上面例子线程不安全,要线程安全可以加个同步锁,不过加了同步锁性能又不好了,加载慢

    public class Singleton {
        private static Singleton instance;
        //定义private构造函数,使类不可以被实例
        private Singleton (){}
    
        /**
         * 懒汉模式,线程安全,懒加载
         * @return
         */
        public static synchronized Singleton getInstance() {
            if (instance == null) {
                instance = new Singleton();
            }
            return instance;
        }
    }
    

    2、饿汉模式
    下面介绍一下单例模式的另外一种实现方式,饿汉模式
    其实现原理就是在类内部全局new一个对象,利用Java虚拟机的类加载机制,保证了线程安全,不过很明显,一创建了,就实例了单例类,会给JVM增加负载

    public class Singleton {
        //定义private构造函数,使类不可以被实例
        private Singleton (){}
    
    
        //加载类的时候,利用JVM的类加载机制创建对象,保证了线程安全,但是效率不好
        private static Singleton instance = new Singleton();
    
        /**
         * 饿汉模式,线程安全,非懒加载
         * @return
         */
        public static Singleton getInstance() {
            return instance;
        }
    }
    

    3、双检锁/双重校验锁(DCL,即 double-checked locking)
    下面介绍一种双检锁的实现方式,这种方式看起来稍稍比较复杂了点,不过可以实现线程安全,同时双检锁的方式可以保证性能比较高

    public class Singleton {
     
        //定义private构造函数,使类不可以被实例
        private Singleton (){}
    
        private volatile static Singleton instance;
    
        /**
         * 双检锁/双重校验锁(DCL,即 double-checked locking)线程安全,懒加载
         * @return
         */
        public static Singleton getInstance(){
            if(instance == null){
                synchronized (Singleton.class){
                    if(instance == null){
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    4、登记式/内部类
    下面用内部类的方式来实现单例模式,这种方式可以和饿汉模式来对比一下
    这种方式和刚才介绍的饿汉模式类似,不过区别就是做到了懒加载,我们可以分析例子。方法就是在单例类里加个内部类,这样做就不会像饿汉模式一样,单例类一加载就实例对象。当调用getInstance方法的时候,才会调用,创建对象。这样就做到了懒加载,同时也是利用JVM保证了线程安全

    public class Singleton {
       
        //定义private构造函数,使类不可以被实例
        private Singleton (){}
    
        public static class SingletonHolder{
            private final static Singleton INSTANCE = new Singleton();
        }
    
        /**
         * 登记式/静态内部类,线程安全,懒加载
         * @return
         */
        public static Singleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
    }
    

    5、枚举模式
    这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制,防止反序列化重新创建新的对象,绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用。

    /**
         * 枚举方式
         */
        public enum Singleton {
            INSTANCE;
            public void whateverMethod() {
            }
        }
    

    相关文章

      网友评论

        本文标题:设计模式之单例模式学习笔记

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