单例模式是指在一个应用(JVM)中,对于某个类的实例只能有一个,所有对于某个类实例的访问都是对于同一个对象的访问 优点:在内存中只有一个实例,减少了内存开销。可以避免对资源的多重占用,设置全局访问点,严格控制访问。 缺点:没有接口,扩展困难。如果需要扩展单例对象,只能修改代码,没有其它途径。
ServletContext, ServletConfig, ApplicationContext, DBPool
2.懒汉式单例模式
package com.architecture.pattern.singleton; /** * @Auth yangyongp * @Create 2020/7/3 23:06 */ public class LazySingletonDemo { private static LazySingletonDemo instance = null; private LazySingletonDemo(){ } public static LazySingletonDemo getInstance(){ if(instance == null){ synchronized (LazySingletonDemo.class){ if(instance == null){ instance = new LazySingletonDemo(); } } } return instance; } } package com.architecture.pattern.singleton; /** * @Auth yangyongp * @Create 2020/7/14 21:42 */ public class LazyInnerClasssSingletonDemo { private LazyInnerClasssSingletonDemo(){ } /** * 懒汉式单例 * LazyHolder里面的逻辑需要等到外部方法调用时才执行 * 巧妙利用了内部的特性 * JVM底层执行逻辑,避免了线程安全问题 * @return */ public static LazyInnerClasssSingletonDemo getInstance(){ return LazyHolder.LAZY; } private static class LazyHolder{ private static final LazyInnerClasssSingletonDemo LAZY = new LazyInnerClasssSingletonDemo(); } } 注册式单例 a.枚举式单例 从JDK层面就为枚举不被序列化和反射破坏来保驾护航 package com.architecture.pattern.singleton; /** * @Auth yangyongp * @Create 2020/7/3 23:10 */ public enum EnumSingletonDemo { INSTANCE; private Object data; public Object getData() { return data; } public void setData(Object data) { this.data = data; } public static EnumSingletonDemo getInstance(){ return INSTANCE; } }b.容器式
package com.architecture.pattern.singleton; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * @Auth yangyongp * 对象方便管理,其实也是属于懒加载 * @Create 2020/7/14 22:25 */ public class ContainerSingletonDemo { private ContainerSingletonDemo(){ } private static Map<String, Object> ioc = new ConcurrentHashMap<>(); public static Object getBean(String className){ if(!ioc.containsKey(className)){ synchronized (ioc){ if(!ioc.containsKey(className)){ Object obj = null; try{ obj = Class.forName(className).newInstance(); ioc.put(className, obj); }catch (Exception ex){ ex.printStackTrace(); } return obj; } } } return ioc.get(className); } }1.私有构造方法 2.保证线程安全 3.延迟加载 4.防止序列化和反序列化破坏单例 5.防止反射攻击