本来不想写这篇的,以为这模式很简单,平时最常用的模式之一。但是昨天面试我回答的却很不好。
为什么叫“单例”,就是整个JVM里面这个对象只有唯一的一个。这个理论“道”的层面。
场景:比如项目里唯一的一个管理员,数据库实例,redis实例、用于创建bean对象的工厂...
如何实现(“术”的层面):只要能实现唯一的一个对象,禁止多次new XXX,所以方法很多....。下面是经典的方法:
1 为了保持唯一,可以构造器 private私有,防止被多次new ();
2 构造器被private了,只能static来实现访问了。
public class Singleton { //static 类加载就实例化 --所以被称为“饿汉”模式-饥不可耐 不管女友什么时候来,先开好房间 private static Singleton instance = new Singleton(); //把类的构造方法私有化,不让外部调用构造方法实例化 private Singleton() { } // 也称为静态工厂方法 // 外部通过调用getInstance()方法来返回唯一的实例 public static Singleton getInstance() { return instance; } }
然后呢,考虑代码优化啊O(∩_∩)O哈哈~ 考虑什么呢?无非就是性能、并发
性能嘛,考虑延迟加载;
并发嘛就是同步锁(当然实现不同的实现方式也有一些小缺点)。
最佳实践:找本设计模式的书。里面有7种变体吧。
那如何区分呢?所以大家给他们取了不同的名字。饿汉式 懒汉式、双重判断加锁方式、menu方式等等
spring中的案例:spring 中的bean,默认都是单例的,它是如何实现的?双重判断加锁。
createBean-doCreateBean(...)-doGetBean(...) 存放在Map容器里面
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}