java设计模式之单例模式你真的会了吗?(饿汉式篇) java设计模式之单例模式你真的会了吗?(饿汉式篇) 一、什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式
java设计模式之单例模式你真的会了吗?(饿汉式篇)
java设计模式之单例模式你真的会了吗?(饿汉式篇)
一、什么是单例模式?
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
二、单例模式之饿汉式有什么特点以及优缺点?
- 构造方法私有化
- 类初始化时自行实例化
- 对外提供统一的静态工厂方法返回实例
- 优点:实现简单,不存在多线程问题。
- 缺点:class类在被加载的时候创建Singleton实例,如果对象创建后一直没有使用,则会浪费很大的内存空间,此方法不适合创建大对象。
三、我们常见的饿汉式单例的写法
public class HungrySingleton implements Serializable{private static final long serialVersionUID = -1008862048413058509L;
private HungrySingleton() {}
//类初始化时自行实例化
private static final HungrySingleton INSTANCE = new HungrySingleton();
//对外提供统一的静态工厂方法返回实例
public static HungrySingleton getInstance() {
return INSTANCE;
}
}
四、上面的单例模式是真的就是单例的吗?运行下面代码中的main方法试试?
public class HungrySingleton implements Serializable{private static final long serialVersionUID = -1008862048413058509L;
private HungrySingleton() {}
//类初始化时自行实例化
private static final HungrySingleton INSTANCE = new HungrySingleton();
//对外提供统一的静态工厂方法返回实例
public static HungrySingleton getInstance() {
return INSTANCE;
}
//测试方法
public static void main(String[] args) {
//序列化
ObjectOutputStream oo;
try {
oo = new ObjectOutputStream(new FileOutputStream(new File("C:/HungrySingleton.txt")));
oo.writeObject(HungrySingleton.getInstance());
oo.close();
} catch (IOException e) {
e.printStackTrace();
}
//反序列化
ObjectInputStream ois;
HungrySingleton hungrySingleton = null;
try {
ois = new ObjectInputStream(new FileInputStream(new File("C:/HungrySingleton.txt")));
hungrySingleton = (HungrySingleton) ois.readObject();
ois.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("是否相同:" + (hungrySingleton == HungrySingleton.getInstance()));
}
}
结论:通过序列化和反序列化的操作后我们成功的破坏了“单例”
五、为什么饿汉式单例会被序列化和反序列化的操作破坏?
结论:反序列化时如果没有readResolve方法则会返回newInstance的实例,所以导致“单例”被破坏了,如果有readResolve方法则会调用此方法,返回readResolve方法返回的对象
六、所以如何防止饿汉式单例被破坏?需要添加一个readResolve方法并且方法中返回实例即可。
public class HungrySingleton implements Serializable{private static final long serialVersionUID = -1008862048413058509L;
private HungrySingleton() {}
//类初始化时自行实例化
private static final HungrySingleton INSTANCE = new HungrySingleton();
//对外提供统一的静态工厂方法返回实例
public static HungrySingleton getInstance() {
return INSTANCE;
}
/**
* 防止采用序列化、反序列化的方式破坏单例
*/
private Object readResolve() {
return INSTANCE;
}
//测试方法
public static void main(String[] args) {
//序列化
ObjectOutputStream oo;
try {
oo = new ObjectOutputStream(new FileOutputStream(new File("C:/HungrySingleton.txt")));
oo.writeObject(HungrySingleton.getInstance());
oo.close();
} catch (IOException e) {
e.printStackTrace();
}
//反序列化
ObjectInputStream ois;
HungrySingleton hungrySingleton = null;
try {
ois = new ObjectInputStream(new FileInputStream(new File("C:/HungrySingleton.txt")));
hungrySingleton = (HungrySingleton) ois.readObject();
ois.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("是否相同:" + (hungrySingleton == HungrySingleton.getInstance()));
}
}
PS:如果你看到了这篇文章,并且觉得对你有帮助,请给个关注和点赞,谢谢!
作者寄语:如果这篇博文对您有所帮助,请给个推荐和收藏吧,谢谢!
作者:野生D程序猿
本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
【文章出处:香港多ip站群服务器 http://www.558idc.com/hkzq.html提供,感恩】