架构系列——架构师必备基础:设计模式之单例模式(Singleton Pattern)

作者专注于Java、架构、Linux、小程序、爬虫、自动化等技术。 工作期间含泪整理出一些资料,微信搜索【程序员高手之路】,回复 【java】【黑客】【爬虫】【小程序】【面试】等关键字免费获取资料。技术交流、项目合作可私聊:shuhao-99999。

目录

前言

一、单例模式优点

1.减少内存开支

2.避免状态切换时的不正确

二、单例模式的实现与选择

1.单例模式的实现

2.怎么选择单例模式

三、单例模式破解

1.1通过反射破解

1.2解决方法

2.1 通过序列化与反序列化破解

2.2 解决方法 

四、单例模式的应用


前言

单例模式,就是在整个应用程序中都只有一个实例,并且提供一个类方法来供全局调用,在编译期间会一直存储在内存中,直到程序退出,系统自动释放此内存。

下面这个图是不是很熟悉,这个是任务管理器。

你可以尝试一下,在一个电脑上,打开一个任务管理器之后,再打开一次任务管理器,这时候桌面上不会产生新的任务管理器!这是单例模式,也就是说,整个windows系统只存在一个任务管理器的实例!

电脑上的回收站也是同样的道理。

一、单例模式优点

一个类只能产生一个实例,这样做的好处有:

1.减少内存开支

当你想关闭QQ进程的时候,可以使用任务管理器;当你想关闭浏览器的时候,也可以使用任务管理器。当然,两次打开的任务管理器其实是同一个任务管理器。这样的话,电脑的CPU就会减少一部分开销!

2.避免状态切换时的不正确

假如打开了两个任务管理器A和B,关闭A里面的QQ的话,那么B中的QQ有那么一刻没有及时更新,微软肯定不能接受这样的效果!

二、单例模式的实现与选择

1.单例模式的实现

网上有很多,这里推荐实现方式:

设计模式之单例模式--runoob

2.怎么选择单例模式

(1)如果单例对象占用资源少,不需要延迟加载,那么枚举式优于饿汉式

(2)如果单例对象占用资源大,需要延时加载,那么静态内部类式优于懒汉式

三、单例模式破解

菜鸟教程给的只是案例,如果没有对代码优化的话,可以通过以下两种方式破解单例!

1.1通过反射破解

/**
 * 测试反射破解单例模式
 */
public class Reflect {

    public static void main(String[] args) throws Exception {
        // 通过反射直接调用私有构造器破解单例模式
        Class<RuleManager> clz = (Class<Singleton>) Class.forName("com.Singleton");
        Constructor<Singleton> constructor = clz.getDeclaredConstructor(null);
        constructor.setAccessible(true);
        Singleton s3 = constructor.newInstance();
        Singleton s4 = constructor.newInstance();
        System.out.println(s3);
        System.out.println(s4);
    }
}

打印出来的s3和s4结果不一样,说明已经破解了!

1.2解决方法

获取对象的时候手动抛出异常

if (instance!=null) {
   throw new RuntimeException();
}

2.1 通过序列化与反序列化破解

//获取单例
Singleton s1 = Singleton.getInstance();
//将序列化到本地文件
FileOutputStream fos = new FileOutputStream("d:/test.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close();
//反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/test.txt"));
Singleton s2 =  (Singleton) ois.readObject();
Singleton s3 =  (Singleton) ois.readObject();
System.out.println(s2);
System.out.println(s3);

2.2 解决方法 

在生成单例的类里加入readResolve方法

private Object readResolve() throws ObjectStreamException {
   return instance;
}

四、单例模式的应用

windows中任务管理器,回收站

常见的工具类

数据库连接类

项目中用于读取配置文件的类

Spring中,每个Bean默认都是单例的,这样便于Spring容器进行管理

网站计数器

Servlet中Application

参考文献:

[1].单例模式--百度百科

[2].设计模式之单例模式--runoob

[3].单例模式在什么地方使用呢 --百度经验

[4].Java设计模式(一)之单例模式

[5].Java反射:框架设计的灵魂

[6].Java 序列化与反序列化

原文地址:https://www.cnblogs.com/shuhao66666/p/12925382.html