zoukankan      html  css  js  c++  java
  • 架构系列——架构师必备基础:设计模式之单例模式(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 序列化与反序列化

  • 相关阅读:
    VS2005调试问题与解决方法集锦
    [转]在.net 2005中,将数据集序列化成二进制,提高远程传输效率
    DotNet 网上相关资源
    NeHE中文学习网址
    Aspx页上设置客户端的缓存时间
    动态调用Win32 Function(API)
    PB调用COM组件
    字段绑定的效率问题
    三维向量类
    用DataTable绑定TreeView的方法
  • 原文地址:https://www.cnblogs.com/shuhao66666/p/12925382.html
Copyright © 2011-2022 走看看