1.单例模式的定义
确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.
2.单例模式的使用场景
确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源,或者某种类型的对象应该有且只有一个.
3.实现单例模式的几个关键点
- 构造函数不对外开放,一般为private
- 通过一个静态方法返回单例对象
- 确保单例类的对象有且只有一个,尤其是在多线程的情况下
- 确定单例类对象在反序列化时不会重新创建对象
4.单例模式的几种实现方式
- 饿汉式
public class RxBus{
private static RxBus instance = new RxBus();
//通过静态方法获取实例
public static RxBus getInstance(){
return instance;
}
private Object readResolve() throws ObjectStreamException{
return instnce;
}
}
饿汉式的缺点就是在声明静态对象时就已经初始化了.在一定程度上造成了资源的浪费
- 懒汉式
private static RxBus instance ;
//私有构造函数,防止new 对象
private RxBus(){
}
//通过静态方法获取实例
public static RxBus getInstance(){
if (instance == null){
synchronized(RxBus.class){
if(instance == null){
instance = new RxBus();
}
}
}
return instance;
}
//防止反序列化的时候生成新的对象
private Object readResolve() throws ObjectStreamException{
return instnce;
}
懒汉式的有点在于既能够在需要时才初始化单例,又能够保证线程安全,这种模式的亮点就在两次非空判断,第一层判断主要是避免不必要的同步,第二层判断则是为了在null的时候才创建实例,防止多次创建.
- 静态内部类单例模式
public class RxBus{
private RxBus(){
}
//通过静态方法获取实例
public static RxBus getInstance(){
return RxBusHolder.instance;
}
//静态内部类
private static class RxBusHolder{
private static final RxBus instance = new RxBus();
}
//防止反序列化的时候生成新的对象
private Object readResolve() throws ObjectStreamException{
return RxBusHolder.instnce;
}
}
这中模式避免了在声明对象时就创建对象,只有在第一次调用getInstance时才会创建对象,这种方式不仅能够保证线程安全,保证单例对象的唯一性,同时也延迟了单例的实例化.
- 使用容器实现单例模式
public class SingleManager{
private static Map<String,Object> objMap = new HashMap();
private SingleManager(){
}
public statice void registerSingleManager(String key ,Objcet instance){
if(!objMap.containsKey(key)){
objMap.put(key,instance);
}
}
public static Object getSingleManager(String key){
return objMap.get(key);
}
}
这种模式的使用就是在程序的初始化的时候,创建好了各种单例对象,然后放到统一的一个管理类中,然后在使用时根据key获取对应的对象.在android的getSystemService方法就是通过这种模式来实现单例的.
总结
无论是那种模式的单例,它们的核心原理都是将构造函数私有化,并且通过静态方法获取唯一的一个实例.在这个获取的过程中必须保证线程安全,防止反序列化的时候导致重新生成实例对象.距离的可以参考Andoird源码设计模式解析与实战一书.