当前位置 : 主页 > 编程语言 > java >

java设计模式之单例模式你真的会了吗?(饿汉式篇)

来源:互联网 收集:自由互联 发布时间:2022-07-04
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()));
}
}

java设计模式之单例模式你真的会了吗?(饿汉式篇)_饿汉式

结论:通过序列化和反序列化的操作后我们成功的破坏了“单例”

五、为什么饿汉式单例会被序列化和反序列化的操作破坏?

java设计模式之单例模式你真的会了吗?(饿汉式篇)_设计模式_02

java设计模式之单例模式你真的会了吗?(饿汉式篇)_设计模式_03

java设计模式之单例模式你真的会了吗?(饿汉式篇)_反序列化_04

java设计模式之单例模式你真的会了吗?(饿汉式篇)_设计模式_05

java设计模式之单例模式你真的会了吗?(饿汉式篇)_java_06

java设计模式之单例模式你真的会了吗?(饿汉式篇)_单例模式_07

java设计模式之单例模式你真的会了吗?(饿汉式篇)_单例模式_08

java设计模式之单例模式你真的会了吗?(饿汉式篇)_java_09

结论:反序列化时如果没有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()));
}
}

java设计模式之单例模式你真的会了吗?(饿汉式篇)_反序列化_10

PS:如果你看到了这篇文章,并且觉得对你有帮助,请给个关注和点赞,谢谢!

作者寄语:如果这篇博文对您有所帮助,请给个推荐和收藏吧,谢谢!

作者:野生D程序猿

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

【文章出处:香港多ip站群服务器 http://www.558idc.com/hkzq.html提供,感恩】
上一篇:手把手教你 SpringBoot整合Redis
下一篇:没有了
网友评论