大家写单例模式的时候有没有这样的困扰:
单例初始化的时候需要一些参数,但是获取单例的时候一般不需要这些参数。传统的单例写法你不得不加上这些参数才可以获取单例对象,这样做是不是很傻呢?
举一个例子,大家常用的数据库操作对象:
public class DbManager {
private static DbManager sInstance;
private final Application mApp;
private DbManager(Application app) {
mApp = app;
}
public static DbManager getInstance(Application app) {
if (sInstance == null) {
synchronized (DbManager.class) {
if (sInstance == null) {
sInstance = new DbManager(app);
}
}
}
return sInstance;
}
}
一般我们这样来获取单例对象:
DbManager manager = DbManager.getInstance(getApplication());
DbManager dbManager = InstancePool.get(DbManager.class);
public static <T> T get(Class<T> clazz)
public static <T> void register(Class<T> clazz, InstanceCreator<T> creator)
public interface InstanceCreator<T> {
T createInstance();
}
所以整个 InstancePool 是这样的:
public class InstancePool {
/**
* 用来保存所有的单例创建回调接口
*/
private static final Map<Class, InstanceCreator> sCreatorMap = new ConcurrentHashMap<>();
/**
* 用于保存所有的单例对象
*/
private static final Map<Class, Object> sInstanceMap = new ConcurrentHashMap<>();
/**
* 先注册某个类是单例类,并指定该类的创建方法
*/
public static <T> void register(Class<T> clazz, InstanceCreator<T> creator) {
sCreatorMap.put(clazz, creator);
}
/**
* 根据单例类,获取单例对象
*/
public static <T> T get(Class<T> clazz) {
Object instance = sInstanceMap.get(clazz);
if (instance == null) {
synchronized (InstancePool.class) {
if (sInstanceMap.containsKey(clazz)) {
instance = sInstanceMap.get(clazz);
} else {
InstanceCreator creator = sCreatorMap.remove(clazz);
if (creator != null) {
instance = creator.createInstance();
sInstanceMap.put(clazz, instance);
}
}
}
}
//noinspection unchecked
return (T) instance;
}
}
这样,我们的 DbManager 就可以简化成这样:
public class DbManager {
private final Application mApp;
public DbManager(Application app) {
mApp = app;
}
}
完全不需要写一大堆 sInstance 相关的代码了。
我已经把代码放到 Github 上了,欢迎大家参考优化。
#Android#