1.单例模式
保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。减少系统开销,new一个对象需要较多的资源,如读取配置文件,产生其他依赖对象,则可以在应用启动时直接产生一个单例对象,然后永久驻留内存的方式解决。
1.1饿汉式:
线程安全,调用效率高,不能延迟加载,资源利用率低 反射和反序列化可以破解
public class SingletonDemo01 {
//初始化类时加载,(没有延时的优势),类加载时是线程安全的
private static SingletonDemo01 instance=new SingletonDemo01();
//私有化构造器
private SingletonDemo01() {
}
//方法没有同步,调用效率高
public static SingletonDemo01 getInstance() {
return instance;
}
}
1.2懒汉式:
线程安全,调用效率低,能延迟加载,资源利用率高 反射和反序列化可以破解
public class SingletonDemo02 {
//类初始化时不初始化对象,(有延时的优势)
private static SingletonDemo02 instance;
//私有化构造器
private SingletonDemo02() {
}
//方法同步,防止多次new对象。调用效率低
public static synchronized SingletonDemo02 getInstance() {
if(instance==null) {
instance=new SingletonDemo02();
}
return instance;
}
}
1.3静态内部类方式:
线程安全,调用效率高,能延迟加载,资源利用率高。反射和反序列化可以破解
public class SingletonDemo03 {
//私有化构造器
private SingletonDemo03() {
}
//静态内部类,加载外部类时不会加载内部类
private static class SingletonInstance{
private static SingletonDemo03 instance=new SingletonDemo03();
}
public static SingletonDemo03 getIntance() {
return SingletonInstance.instance;
}
}
1.4枚举:
枚举元素本身就是单例对象(不能延迟加载)反射和反序列化不可以破解
2.防止破解单例模式
- 破解:反射通过获取构造器,创建多个对象
a.防止单例模式被反射破解:在私有构造器里面判断是否已经有一个实例存在,是则抛异常
b.防止反序列化破解:在单例类中添加代码
private Object readResolve() throws ObjectStreamException{
return instance;
}