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


    单例模式 


    • 单例模式是一个比较简单的模式,其定义如下

    确保每个类只有一个实例,并且本类实例化对象提供给整个系统(Ensure a class has only one instance, and provide a global point of access to it)

    • 单例模式的通用类图如下

        如上图中的通用类图仅是单例模式中的饿汉模式,其中单例模式还包括懒汉模式、静态内部类、双重校验锁等方式,如下依次通过代码呈现给大家:

    public class Singleton {
        //在Singleton类加载时就回创建singleton对象
        private static Singleton singleton = new Singleton();
        private Singleton() {}
        public static Singleton getInstance() {
            return Singleton.singleton;
        }
    }
    饿汉模式

        饿汉模式是基于classloder机制避免了多线程的同步问题,这也使得singleton对象在类装载时就实例化,而我们更希望是在调用getInstance()方法时实例化singleton对象,这样才能达到lazy loading的效果。而懒汉模式就实现了这一愿望。

    public class Singleton{
        private static Singleton singleton = null;
        private Singleton() {}
        //通过synchronized关键字对getInstance方法加锁
        public static synchronized Singleton getInstance() {
            if(singleton == null) {
                singleton = new Singleton();
            }
            return Singleton.singleton;
        }
    }
    懒汉模式

        懒汉模式虽然能够在多线程种很好的工作,而且看起来也具备很好的lazy loading,但是我们并不需要每一次调用getInstance方法都加锁,效率很低。为了解决懒汉模式中效率低下的问题,我们采用静态内部类的方式。

    public class Singleton{
        private Singleton() {}
        //静态内部类
        private static class SingletonHandler{
            private static final Singleton singleton = new Singleton();
        }
        public static Singleton getInstance() {
            return SingletonHandler.singleton;
        }
    }
    静态内部类

        静态内部类同样利用了classloder的机制来保证初始化instance时只有一个线程,而且实现了当Singleton类被装载时并不立即初始化instance。因为SingletonHandler类没有被主动使用,只有显示通过调用getInstance方法时,才会显示装载SingletonHandler类,从而实例化instance。想象一下,如果实例化instance很消耗资源,我想让他延迟加载,另外一方面,我不希望在Singleton类加载时就实例化,因为我不能确保Singleton类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化instance显然是不合适的。

    public class Singleton{
        private static Singleton singleton = null;
        private Singleton() {}
        public static Singleton getInstance() {
            if(singleton == null) {
                synchronized(Singleton.class) {   //对Singleton类加锁
                    if(singleton == null) {
                        singleton = new Singleton();
                    }
                }
            }
            return singleton;
        }
    }
    双重校验锁
    • 单例模式的优点:
      • 由于单例模式在内存中只有一个对象,减少了内存开销,当一个对象需要频繁的创建、销毁时,单例模式能提示实例创建时的效率,
      • 单例模式减少了内存开销,当一个对象的产生需要比较多的资源时,可以考虑单例模式,创建一个单例对象常驻内存(在Java EE中采用单例模式注意垃圾回收),
      • 单例模式避免对资源的多重占用,
      • 单例模式可以在系统设置全局访问点,优化和共享资源访问,例如可以设计单例模式负责所有数据表的映射处理。
    • 单例模式的缺点
      • 单例模式一般没有接口,扩展困难,
      • 单例模式对测试是不利的,如果单例模式没有完成,是不能进行测试的,没有接口也不能使用mock的方式虚拟一个对象,
      • 单例模式与单一职责原则冲突。一个类应该只实现一个逻辑,而不关心它是否是单例模式,单例模式把“单例”和业务逻辑融合在一个类中。
    • 单例模式的扩展

    单例模式是一个类只能产生一个对象的模式,如果一个类可以产生指定个对象,则需要对单例模式做一些变动

    • 变动后的类图如下

    • 最佳实践

    在Spring中,每个Bean默认就是单例的,这样做的优点就是Spring容器可以管理这些Bean的生命周期,决定什么时候创建出来,什么时候销毁等等。如果采用非单例模式(prototype类型),则Bean初始化后的管理交由J2EE容器,Spring不再跟踪管理Bean的生命周期。

  • 相关阅读:
    从零开始写STL-容器-双端队列
    JVM 总结
    从零开始写STL-容器-list
    从零开始写STL—容器—vector
    Web 后端编程的几个关键点(总结中...)
    Java Web 总结
    Spring实战读书笔记
    MSDN 同步部分 个人笔记
    洛谷 P3391【模板】文艺平衡树(Splay)
    洛谷 P1503 鬼子进村
  • 原文地址:https://www.cnblogs.com/zhanglei93/p/5974894.html
Copyright © 2011-2022 走看看