Java的单例模式实现方式一直是各路“大神”讨论的重点。
人们往往会去关注是否线程安全,是否支持懒加载,以前老版本Java的双检锁问题,volatile happen-before 问题,学究式的枚举类式实现。
我们真的需要了解这么多细节吗?
真的需要同时靠这么多trick来实现业务吗?
一门良好的编程语言不是应该让我们简单快乐地表达自己的目的吗?
编程语言不是应该为我们服务吗?难道要我们去伺候一门编程语言?
必须搞懂这么多trick才能称为“熟练”“精通”吗?
这么纠结于这些近乎为“语言糟粕”的特征是不是“孔乙己式”的行为?(茴香豆的茴字有几种写法?)
单例模式一种方式就够
作为Java的使用者,我们只需要知道这一种方法就行:
看看人家JDK自己是怎么实现的!!!
Java代码
-
package java.lang;
-
public class Runtime {
-
private static final Runtime currentRuntime = new Runtime();
-
-
public static Runtime getRuntime() {
-
return currentRuntime;
-
}
-
-
private Runtime() {}
-
-
...
-
}
杠精说这个实现不满足懒加载。
实际项目中需要懒加载的单例场景有多少?那就再来个“内部类式”的实现:
Java代码
-
public class Singleton {
-
private Singleton() {}
-
public static Singleton getSingleton() {
-
return Holder.singleton;
-
}
-
-
private static class Holder {
-
private static final Singleton singleton = new Singleton();
-
}
-
}
Spring 中 Bean 的单例实现方式
Spring中的Bean默认是单例的。这个效果不是上述通过改变类的实现来达到的。
上述单例模式的类无法被继承,因为子类无法调用父类的 private 构造函数。
Spring 采用 单例注册表 的方式来达到单例的效果(AbstractBeanFactory)。
可以简单地理解为,有一个 Map<Class<?>, Object> 存储每个目标类的唯一实例;通过类型信息获得相应的实例。