确保某个类只有一个实例,并且自行实例化并向整个系统提供这个实例。java
- Client:高层客户类
- Singleton:单例类
- 构造函数不对外开放,通常为Private
- 经过一个静态方法或枚举返回单例类对象
- 确保单例类的对象有且只有一个,尤为在多线程环境下
- 确保单例类对象在反序列化时不会从新构建对象
- 饿汉:在声明时就初始化
/** * 饿汉单例 */ public class MySingleton { // 饿汉单例,在声明时就初始化 private static MySingleton ourInstance = new MySingleton(); public static MySingleton getInstance() { return ourInstance; } private MySingleton() { } }- 懒汉:只有在使用时才会实例化,在必定程度上节省了资源;缺点是第一次加载时须要及时进行实例化,反应稍慢,最大的问题是每次调用getInstance都要进行同步,形成没必要要的同步开销。这种模式通常不建议采用。
/** * 懒汉单例 */ public class MySingleton { private static MySingleton ourInstance; public static synchronized MySingleton getInstance() { // 懒汉单例,只有在使用才会实例化 if (ourInstance == null) { ourInstance = new MySingleton(); } return ourInstance; } private MySingleton() { } }- DCL:Double Check Lock。优势是既可以在须要时实例化单例,又能保证线程安全,且单例对象初始化后调用getInstance不进行同步锁。
/** * Double Check Lock(DCL) */ public class MySingleton { private static MySingleton ourInstance = null; private MySingleton() {}; public static MySingleton getInstance() { // 避免没必要要的同步 if (ourInstance == null) { synchronized (MySingleton.class) { // 建立实例 if (ourInstance == null) { ourInstance = new MySingleton(); } } } return ourInstance; } }- 静态内部类:当第一次加载Singleton类时并不会初始化,只有在第一次调用时才会初始化。所以,第一次调用getInstance方法会致使虚拟机加载SingleHolder类,这种方式不只可以确保线程安全,也能保证单例对象的惟一性,同时也延迟了单例实例化,因此这是推荐使用的单例模式实现方式。
/** * 静态内部类单例模式 */ public class MySingleton { private MySingleton() {}; public static MySingleton getInstance() { return SingletonHolder.ourInstance; } /** * 静态内部类 */ private static class SingletonHolder { private static MySingleton ourInstance = new MySingleton(); } }- 枚举单例:枚举单例是线程安全的,而且在任何状况下它都是一个单例。且没法经过反序列化获得对象。
/** * 枚举单例 */ public enum SingletonEnum { INSTANCE; public void dosomething() { System.out.println("do sth."); } }- 使用容器实现单例
/** * 使用容器实现单例模式 */ public class SingletonManager { private static Map<String, Object> objMap = new HashMap<>(); private SingletonManager() {} 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); } }
getSystemService 经过容器实现单例 安全