意图
保证一个类仅有一个实例,并提供一个全局访问结点。
适用性
- 类只能有一个实例,客户可以从一个众所周知的结点访问它。
- 当这个唯一实例通过子类化可扩展的,客户无需更改代码就能使用一个扩展的实例。
效果
- 对唯一实例的受控访问——单例类封装其唯一实例,所以可以控制客户何时及怎样访问它。
- 缩小名字空间——单例模式是一种对全局变量的改进.
- 允许对操作和表示的精化——Singleton类可以有子类,允许在运行时配置应用。
- 允许可变数目的实例——可以用相同的方法控制实例的数目。
- 比类操作更灵活
实现方式
饿汉式
/*** 饿汉式实现单例模式** @author Jinhua* @date 2020/8/22 22:47*/public class SingletonHungry implements MySingleton {/*** 类加载准备阶段的时候就进行初始化*/private static final SingletonHungry INSTANCE = new SingletonHungry();private SingletonHungry() {}public static SingletonHungry getInstance() {return INSTANCE;}@Overridepublic void doSomething() {System.out.println(this + "\t饿汉实现单例模式");}}
懒汉式(线程不安全)
/*** 懒汉模式单例(线程不安全)** @author Jinhua* @date 2020/8/22 22:49*/public class SingletonLazy implements MySingleton {private static SingletonLazy instance = null;private SingletonLazy() {}/*** 模拟多线程下不安全的问题** @return 返回单例对象* @throws InterruptedException 中断异常*/public static SingletonLazy getInstance() throws InterruptedException {if (instance == null) {// 睡眠用于模拟线程不安全的问题Thread.sleep(5000);instance = new SingletonLazy();}return instance;}@Overridepublic void doSomething() {System.out.println(this + "\t懒汉实现单例模式.");}}
懒汉式(线程安全)
/*** 懒汉模式单例(线程安全)** @author Jinhua* @date 2020/8/22 22:52*/public class SingletonLazyThread implements MySingleton {private static SingletonLazyThread instance;private SingletonLazyThread() {}/*** 测试多线程环境下线程安全的懒汉实现单例** @return 单例对象* @throws InterruptedException 中断异常*/public static synchronized SingletonLazyThread getInstance() throws InterruptedException {if (instance == null) {// 睡眠用于模拟线程的问题Thread.sleep(5000);instance = new SingletonLazyThread();}return instance;}@Overridepublic void doSomething() {System.out.println(this + "\t线程安全的懒汉单例模式.");}}
双重检查模式
/*** 双重检查的单例模式** @author Jinhua* @date 2020/8/22 22:39*/public class SingletonDoubleCheck implements MySingleton {private static volatile SingletonDoubleCheck instance = null;private SingletonDoubleCheck() {}public static SingletonDoubleCheck getInstance() {// 避免多次进入同步判断,影响性能if (instance == null) {synchronized (SingletonDoubleCheck.class) {// 同步块中的判断,保证唯一if (instance == null) {instance = new SingletonDoubleCheck();}}}return instance;}@Overridepublic void doSomething() {System.out.println(this + "\t双重检查单例模式");}}
枚举单例
/*** 枚举实现单例** @author Jinhua* @date 2020/8/22 23:03*/public enum SingletonEnum implements MySingleton {/*** 单例的枚举*/INSTANCE;private Object readResolve() throws ObjectStreamException {return INSTANCE;}@Overridepublic void doSomething() {System.out.println(this + "\t枚举单例模式.");}public static MySingleton getInstance() {return SingletonEnum.INSTANCE;}}
静态内部类单例
/*** 静态内部实现类单例模式** @author Jinhua* @date 2020/8/22 23:02*/public class SingletonStaticInnerClass implements MySingleton {private SingletonStaticInnerClass() {}public static SingletonStaticInnerClass getInstance() {return SingletonHolder.S_INSTANCE;}@Overridepublic void doSomething() {System.out.println(this + "\t静态内部类实现单例模式.");}/*** 静态内部类中引用当前对象*/private static class SingletonHolder {private static final SingletonStaticInnerClass S_INSTANCE = new SingletonStaticInnerClass();}}
管理单例对象
容器管理单例对象
/*** 使用容器管理单例对象** @author Jinhua* @date 2020/8/22 23:05*/public class SingletonManager {/*** 存储单例对象的 map*/private static final Map<String, Object> OBJ_MAP = new HashMap<>();private SingletonManager() {}/*** 注册到 map 中的方法* @param key 注册的键* @param instance 单实例*/public static void registerService(String key, Object instance) {if (!OBJ_MAP.containsKey(key)) {OBJ_MAP.put(key, instance);}}/*** 获取根据键单实例的服务* @param key 键* @return 单例*/public static Object getService(String key) {return OBJ_MAP.get(key);}}
