设计模式是软件从业者长期以来总结的对特殊问题的解决方法,合理的使用设计模式可以很好的解决在开发中出现的问题。
单例模式 也是设计模式中最简单的一个设计模式,它的作用是保证一个类的对象在系统中唯一性。
单例模式解决了,对于频繁使用类创建对象的操作,这可以减少创建对象所需要的时间。对于频繁使用new创建对象来说,可以减少系统的使用频率,减轻GC的压力,缩短GC的处理时间。
单例模式内容
单例模式包含两个角色 单例类 和单例使用者
角色 | 作用 |
单例类 | 创建类对象 保证对象唯一性 |
类使用者 | 使用单例对象 |
他的基本结构如图1.1
图 1.1 单例模式结构图
单例模式的核心就是 三私一公
私有化构造方法(这点非常重要,私有化构造方法可以防止通过new 创建对象)
私有化静态变量(用于存储类的实例化对象)
私有化克隆方法(避免通过公共方法获取实例后再通过clone克隆对象,这样就会产生出一个对象 这样就不能保证唯一了)
公共的静态方法(用于获取实例化对象)
/** * @author: yzjcsdn * @create 2018/4/17 14:56 * @Description: */ public class SingletonTest1 { /** * 私有化构造方法 */ private SingletonTest1() { System.out.println("私有化构造方法"); } /** * 私有化静态变量 */ private static SingletonTest1 singletonTest1 = new SingletonTest1(); /** * 公共的获取对象的方法 * * @return */ public static SingletonTest1 getInstance() { return singletonTest1; } /** * 重写clone方法 * @return * @throws CloneNotSupportedException */ @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
上面的场景 并没有使用单例类 对象依然是被创建出来的 这样就为违背了单例的初衷因此需要改进上面的代买 如下
/** * @author: yzjcsdn * @create 2018/4/17 14:59 * @Description: */ public class LazySingleton { private LazySingleton() { System.out.println("懒加载单例"); } private static LazySingleton lazySingleton = null; public static synchronized LazySingleton getInstance() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; } }
上面的部分引入了懒加载机制
此时要将获取实例的方法加上synchronize 对象锁,这样可以保证在多线程的情况下 获取的对象也是唯一性的,但是同样会出现一个问题性能问题
此外还可以使用内部类的方式创建单例对象。
/** * @author:yzjcsdn * @create 2018/4/17 16:27 * @Description: */ public class ClazzSingtelon { private ClazzSingtelon(){ System.out.println("内部类方式"); } private static class ClazzSingtelonHolder{ private static ClazzSingtelon clazzSingtelon = new ClazzSingtelon(); } private static ClazzSingtelon getInstance(){ return ClazzSingtelonHolder.clazzSingtelon; }使用内部类的方式获取单例对象,当 ClazzSingtelon被加载时,其内部并不会被初始化,因此可以确保当ClazzSingtelon类被载入JVM时,并不会初始化单例类,而当getInstance()方法被调用时,才会加载ClazzSingtelonHolder,从而初始化instance。同同时,由于实例的简历是在类加载的时候完成,所以天生对多线程友好,getInstance()方法也不需要使用同步关键字。
通常情况下使用以上解决方法可以实现单例模式。但是仍然有例外情况,可能导致系统中生成多个实例,比如,在代码中通过单摄机制,强行调用单例的私有函数,生成多个单例,这些都是特殊性。
单例模式在Spirng中的应用
spring 初始化bean 默认是单例的 那么他的实现是怎样的呢?