创建型模式-单例模式
2017-02-07 本文已影响0人
顾树旺
单例模式简介
使用场景
- 整个系统只需要一个全局对象
- 这个对象很耗费资源(如需要IO、数据库等),没有理由让它构造多个实例
角色
- Client-高层客户端
- Singleton-单例类
关键点
- 构造函数不对外开放,一般为Private
- 通过一个静态方法或者枚举返回单例类对象
- 确保单例类的对象有且只有一个,尤其是在多线程环境下
- 确保单例类对象在反序列化时不会重新构建对象
实现方式
- 饿汉方式
- 懒汉方式 (不建议使用)
- 单例使用时才实例化,节约了资源
- 第一次加载时需要实例化,反应稍慢
- 大问题:每次调用都需要同步,造成不必要的开销
- Double CheckLock (DCL) 方式
- Java1.5之前的JMM中缓存的问题
- 需要在java6开始使用volatile
- 是使用最多的使用方式
- 可能会失效
- 静态内部类单例模式
- 《Java并发编程实战》推荐使用
- 枚举单例
- 可以保证反序列化不创建新的实例
- 其他方式应对反序列化,必须再readResolve()中返回sInstance
- 使用容器实现
优点
- 减少内存开支
- 减少了系统的性能开销
- 避免对资源的多重占用
- 可以在系统设置全局的访问点,优化和共享资源访问
缺点
- 一般没有接口,扩展很困难,除了修改代码,几乎没有别的办法
- 单例对象保存的其他对象引用,注意不要引起内存泄露
单例模式的具体实现
饿汉方式
public class Singleton {
private static final Singleton sInstance = new Singleton();
// ...
public static Singleton getInstance() {
return sInstance;
}
private Singleton() {
// ...
}
}
懒汉方式
public class Singleton {
private static Singleton sInstance;
// ...
public static synchronized Singleton getInstance() {
if (sInstance == null) {
sInstance = new Singleton();
}
return sInstance;
}
private Singleton() {
// ...
}
}
Double CheckLock (DCL) 方式
public class Singleton {
private static volatile Singleton sInstance;
// ...
public static Singleton getInstance() {
if (sInstance == null) {
synchronized (Singleton.class) {
if (sInstance == null) {
sInstance = new Singleton();
}
}
}
return sInstance;
}
private Singleton() {
// ...
}
}
静态内部类单例模式
public class Singleton {
public static Singleton getInstance() {
return SingletonHolder.sInstance;
}
private Singleton() {
// ...
}
private static class SingletonHolder {
private static final Singleton mInstance = new Singleton();
}
}
枚举单例
public enum SingletonEnum {
INSTANCE;
public void doSomething() {
// ...
}
}
使用容器实现
public class SingletonManager {
private static Map<String, Object> objMap = new HashMap<String, Object>();
public static void registerService(String key, Object instance) {
if (!objMap.containsKey(key)) {
objMap.put(key, instance);
}
}
public static Object getService(String, key) {
return objMap.get(key);
}
private SingletonManager() {
}
}