单例设计模式

简介: 该博客描述了一些, 单例设计模式通过反射破解和序列化破解的解决方案, 作者还是推荐实现最后介绍的 JDK 新特性 enum

常见的五种单例模式实现方式– 主要:

  • 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
  • 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
  • 其他:

    • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
    • 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
    • 枚举式(线程安全,调用效率高,不能延时加载。并且可以天然的防止反射和反序列化漏洞!)
  • 如何选用?

    • 单例对象 占用 资源 少,不需要 延时加载

      • 枚举式 好于 饿汉式
    • 单例对象 占用 资源 大,需要 延时加载:

      • 静态内部类式 好于 懒

饿汉

public class OneObject {

    private static final OneObject OBJECT = new OneObject();
    
    private OneObject () {}
    
    public static OneObject build () {
        return OBJECT;
    }
    
}

懒汉

public class OneObjectLaz {
    
    private static OneObjectLaz laz;
    
    private OneObjectLaz () {}
    
    public static OneObjectLaz build () {
        synchronized (OneObjectLaz.class) {
            if (null == laz) laz = new OneObjectLaz();
        }
        
        return laz;
    }
    
}

多线程测试

for (int i = 0; i < 10; i++) {
    new Thread(() -> {
        OneObjectLaz build = OneObjectLaz.build();
        System.out.println(build.hashCode());
    }).start();
}

通过反射机制暴力范围 private 构造器, 从而达到多实例

Constructor<OneObject> constructor = OneObject.class.getDeclaredConstructor();

constructor.setAccessible(true);

OneObject newInstance = constructor.newInstance();

System.out.println(newInstance);

解决方案

public class OneObjectLaz {
    
    private static OneObjectLaz laz;
    
    private OneObjectLaz () {
        if (laz != null) throw new RuntimeException("对象必须保证单例!");
    }
    
    public static OneObjectLaz build () {
        synchronized (OneObjectLaz.class) {
            if (null == laz) laz = new OneObjectLaz();
        }
        
        return laz;
    }
    
}

防止序列化破解单例

public class OneObjectLaz {
    
    private static OneObjectLaz laz;
    
    private OneObjectLaz () {
        if (laz != null) throw new RuntimeException("对象必须保证单例!");
    }
    
    public static OneObjectLaz build () {
        synchronized (OneObjectLaz.class) {
            if (null == laz) laz = new OneObjectLaz();
        }
        
        return laz;
    }
    
    /**
     * 防止单例, 反序列化破解
     * 如果定义了: readResolve 方法在反序列时直接返回方法指定的对象, 不需要new了
     */
    private Object readResolve() throws ObjectStreamException {
        return laz;
    }
    
}

要想真正的实现单利漏洞还是很多的所以jdk提供了新特性: enum

public enum One {

    ONE, TWO, THREE;
    
}
目录
相关文章
|
7月前
|
设计模式
单例设计模式步骤
单例设计模式步骤
35 1
|
7月前
|
设计模式 安全 测试技术
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
【C/C++ 设计模式 单例】单例模式的选择策略:何时使用,何时避免
147 0
|
7月前
|
设计模式 安全 Java
最简单的设计模式是单例?
单例模式可以说是Java中最简单的设计模式,但同时也是技术面试中频率极高的面试题。因为它不仅涉及到设计模式,还包括了关于线程安全、内存模型、类加载等机制。所以说它是最简单的吗?
82 3
最简单的设计模式是单例?
|
7月前
|
设计模式 安全 Java
【设计模式】2、设计模式分类和单例设计模式
【设计模式】2、设计模式分类和单例设计模式
59 0
|
7月前
|
设计模式 消息中间件 安全
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
多线程编程设计模式(单例,阻塞队列,定时器,线程池)(二)
62 1
|
7月前
|
设计模式 Java
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
26、Java 简单实现单例设计模式(饿汉式和懒汉式)
58 2
|
7月前
|
设计模式 安全 Java
在Java中即指单例设计模式
在Java中即指单例设计模式
41 0
|
17天前
|
设计模式 前端开发 JavaScript
JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式
本文深入探讨了JavaScript设计模式及其在实战中的应用,涵盖单例、工厂、观察者、装饰器和策略模式,结合电商网站案例,展示了设计模式如何提升代码的可维护性、扩展性和可读性,强调了其在前端开发中的重要性。
22 2
|
3月前
|
设计模式 存储 安全
设计模式——设计模式介绍和单例设计模式
饿汉式(静态常量)、饿汉式(静态代码块)、懒汉式(线程不安全)、懒汉式(线程安全,同步方法)、懒汉式(线程不安全,同步代码块)、双重检查(推荐,线程安全、懒加载)、静态内部类(推荐)、枚举(推荐)
设计模式——设计模式介绍和单例设计模式
|
4月前
|
设计模式 JavaScript 前端开发
从工厂到单例再到策略:Vue.js高效应用JavaScript设计模式
【8月更文挑战第30天】在现代Web开发中,结合使用JavaScript设计模式与框架如Vue.js能显著提升代码质量和项目的可维护性。本文探讨了常见JavaScript设计模式及其在Vue.js中的应用。通过具体示例介绍了工厂模式、单例模式和策略模式的应用场景及其实现方法。例如,工厂模式通过`NavFactory`根据用户角色动态创建不同的导航栏组件;单例模式则通过全局事件总线`eventBus`实现跨组件通信;策略模式用于处理不同的表单验证规则。这些设计模式的应用不仅提高了代码的复用性和灵活性,还增强了Vue应用的整体质量。
59 1