本文主要是介绍设计模式:单利模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
单例模式是保证系统实例唯一性的重要手段。单例模式首先通过将类的实例化方法私有化来防止程序通过其他方式创建该类的实例,然后通过提供一个全局唯一获取该类实例的方法帮助用户获取类的实例,用户只需也只能通过调用该方法获取类的实例。下面列举常用单利模式的写法:
饿汉式单利模式
/*** 恶汉式单利模式** @Author: ganbo* @Date: 2020/6/8 20:42*/
public class HungrySingleton {private static HungrySingleton instance = new HungrySingleton();private HungrySingleton() {}public static HungrySingleton getInstance() {return instance;}
}
懒汉式单例模式
/*** 懒汉式单利模式** @Author: ganbo* @Date: 2020/6/8 20:44*/
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static synchronized LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
实现了在使用的时候在初始化,但是这里通过synchronized关键字“加锁”实现避免重复初始化,这样做虽然实现了延迟加载并且避免了重复初始化,但是每次获取该对象都要排队获得锁,在并发较高的场景下效率很低不可取。
双重检查锁式单利
/*** 双重检查锁模式单利模式** @Author: ganbo* @Date: 2020/6/8 20:57*/
public class DoubleCheckSingleton {/*** 这里用volatile修饰的目的就是禁止指令重排序*/private volatile static DoubleCheckSingleton instance;private DoubleCheckSingleton() {}public static DoubleCheckSingleton getInstance() {//检查是否需要阻塞if (instance == null) {synchronized (DoubleCheckSingleton.class) {if (instance == null) {instance = new DoubleCheckSingleton();}}}return instance;}
}
静态内部类式单利(推荐)
/*** 静态内部类方式单利模式** @Author: ganbo* @Date: 2020/6/8 20:55*/
public class StaticInnerClassSingleton {private static class SingletonHolder {private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton();}private StaticInnerClassSingleton() {//防止通过反射破解该单利模式if(SingletonHolder.instance!=null){throw new RuntimeException("不允许重复实例化");}}public StaticInnerClassSingleton getInstance() {return SingletonHolder.instance;}
}
静态内部类通过在类中定义一个静态内部类,将对象实例的定义和初始化放在内部类中完成,我们在获取对象时要通过静态内部类调用其单例对象。之所以这样设计,是因为类的静态内部类在JVM中是唯一的,这很好地保障了单例对象的唯一性,同时静态内部类实在使用到的时候才会加载,这样也实现了“延迟加载”的效果。这里在构造方法中加了判断的目的就是为了用反射暴力破解该单利模式,以上所有单利模式按理来说都要在构造方法中这样判断处理,防止被反射暴力破解。推荐使用。
枚举式单利
/*** 枚举式单利* Created by gan on 2020/6/8 22:01.*/
public enum EnumSingleton {INSTANCE;public static EnumSingleton getInstance(){return INSTANCE;}}
容器式单利
/*** 容器式单利模式* Created by gan on 2020/6/8 22:40.*/
public class ContainerSingleton {private static Map<String, Object> ioc = new ConcurrentHashMap();private ContainerSingleton() {}public static Object getInstance(String beanName) {Object instance = ioc.get(beanName);if (instance != null) {return ioc.get(beanName);} else {synchronized (ContainerSingleton.class) {if (getInstance(beanName) == null) {try {instance = Class.forName(beanName).newInstance();ioc.put(beanName, instance);} catch (Exception e) {e.printStackTrace();}}return instance;}}}
}
该方式是模拟了Spring IOC容器的实现。通过阅读Spring IOC源码可以查看到该种方式。
注意:上面的单利模式都可以通过序列化的方式暴力破解,决绝序列化暴力破解的方法就是在单利类中新增一个readResolve()方法,并且返回已经定义好的实例对象,可以通过将对象序列化和反序列化的方式验证。具体的单利写法如下,这里用饿汉式举例:
/*** 恶汉式单利模式** @Author: ganbo* @Date: 2020/6/8 20:42*/
public class HungrySingleton {private static HungrySingleton instance = new HungrySingleton();private HungrySingleton() {}public static HungrySingleton getInstance() {return instance;}//新增readResolve方法,方式通过序列化和反序列的方式暴力破解private Object readResolve(){return instance;}
}
这篇关于设计模式:单利模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!