单例模式
1 定义
Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)
2 单例通用代码
public class Singleton {
private static final Singleton singleton = new Singleton();
/**
* 构造函数设为私有,以防外部调用。
*/
private Singleton(){
}
/**
* 暴露外部访问方法
* @return
*/
public static Singleton getInstance(){
return singleton;
}
}
3 使用场景
在项目一个类要求只能有一个对象的时候,或者避免产生多个对象去访问资源。
4 单例的优点
- 单例在内存中只有一个实例,减少内存开销。
- 单例只生成一个实例,减少系统性能开销,比如读取文件之类的通过单例产生后常住内存中。
- 单例可以避免统一资源的多重占用,比如读写文件。
- 单例可以在系统设置全局访问点,优化和共享资源访问。
5 单例的缺点
- 单例没有接口,扩展困难。
- 单例与单一职责有冲突。这个看具体情况。
6 单例类型
Double Check Lock (DCL)
public class DoubleSingleton {
private static DoubleSingleton mInstance;
private DoubleSingleton(){}
public static DoubleSingleton getInstance(){
//第一次判空,当不为空的时候直接返回,避免触发同步锁.
if(mInstance == null){
synchronized (DoubleSingleton.class){
//第二次判空,为空的时候创建mInstance对象
if(mInstance == null){
mInstance = new DoubleSingleton();
}
}
}
return mInstance;
}
}
静态内部类单例模式
public class StaticInnerSingleton {
private StaticInnerSingleton(){}
public static StaticInnerSingleton getInstance(){
return SingletonHolder.INSTANCE;
}
/**
* 静态内部类,内部有一个静态变量INSTANCE
*/
private static class SingletonHolder{
private static final StaticInnerSingleton INSTANCE = new StaticInnerSingleton();
}
}
静态内部类单例模式,当StaticInnerSingleton初始化的时候不会创建,而当调用getInstance的时候才会创建SingletonHolder静态内部类,才在内存初始化对象。
枚举单例类型
public enum EnumSingleton {
INSTANCE;
public String getStr(){
return "123";
}
}
使用容器实现单例
public class SingletonManager {
private static Map<String,Object> singletorManager = new HashMap<String,Object>();
private SingletonManager(){}
public static void regisetService(String key,Object instance){
if(!singletorManager.containsKey(key)){
singletorManager.put(key,instance);
}
}
public static Object getService(String key){
return singletorManager.get(key);
}
}
public class SingletonManagerTest {
@Before
public void setUp() throws Exception {
SingletonManager.regisetService("DoubleSingleton",DoubleSingleton.getInstance());
SingletonManager.regisetService("EnumSingleton",EnumSingleton.INSTANCE);
SingletonManager.regisetService("StaticInnerSingleton",StaticInnerSingleton.getInstance());
}
@Test
public void getService() throws Exception {
assertNotNull(SingletonManager.getService("DoubleSingleton"));
}
}