设计模式系列—单例设计模式( 三 )
静态内部类代码示例package com.niuh.designpattern.singleton.v7;/** * 静态内部类完成 , 推荐使用 */public class Singleton {// 添加 volatile 关键字 , 防止指令重排private static volatile Singleton instance;// 构造函数私有化private Singleton() {}// 写一个静态内部类 , 该类中有一个静态属性 Singletonprivate static class SingletonInstance {privatestatic final Singleton INSTANCE = new Singleton();}// 提供一个静态的公有方法 , 直接返回 SingletonInstance.INSTANCEpublic static synchronized Singleton getInstance() {return SingletonInstance.INSTANCE;}}
优缺点
- 本质上是利用类的加载机制来保证线程安全
- 只有在实际使用的时候 , 才会触发类的初始化 , 所以也是懒加载的一种形式 。
- 优点:避免了线程不安全 , 利用静态内部类特点实现延迟加载 , 效率高
枚举代码示例
package com.niuh.designpattern.singleton.v8;/** * 使用枚举 , 可以实现单例, 推荐 */public enum Singleton {INSTANCE; // 属性public void hello() {System.out.println("hello word~");}} class SingletonTest08 {public static void main(String[] args) {Singleton instance1 = Singleton.INSTANCE;Singleton instance2 = Singleton.INSTANCE;System.out.println(instance1 == instance2);System.out.println(instance1.hashCode());System.out.println(instance2.hashCode());instance1.hello();}}
优缺点- 天然不支持反射创建对应的实例 , 且有自己的反序列化机制
- 利用类加载机制保证线程安全
反射攻击实例我们拿饿汉模式作为例子进行测试 , 饿汉模式的代码如下:
package com.niuh.designpattern.singleton.reflect;/** * 饿汉模式防止反射攻击 */public class HungrySingleton {private static final HungrySingleton instance;private HungrySingleton(){}static {instance = new HungrySingleton();}public static HungrySingleton getInstance(){return instance;}private Object readResolve(){return instance;}}
先写一个利用反射获取实例的方法和直接获取实例的方法 , 将两者的返回值进行比较 , 看返回的是否是一个实例 。 代码如下:package com.niuh.designpattern.singleton.reflect;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;/** * 反射攻击实例 */public class Reflectattack {public static void main(String[] args) throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException {Constructor declaredConstructor = HungrySingleton.class.getDeclaredConstructor();declaredConstructor.setAccessible(true);HungrySingleton hungrySingleton = declaredConstructor.newInstance();HungrySingleton instance = HungrySingleton.getInstance();System.out.println(hungrySingleton);System.out.println(instance);System.out.println(hungrySingleton == instance);}}
- SpringBoot2.x入门到项目实战课程系列(第二章)
- 设计模式6之代理模式
- 三星Note10系列One UI Beta版计划正式推送
- LetsGoDigital分享三星Galaxy S21系列全家桶渲染图
- AMD锐龙5000系列处理器曝光 Zen3架构加持性能提升
- 不愧为华为的“狼崽”,刚撇清关系没多久,一系列的动作随之而来
- 三星Galaxy S20系列壁纸,拥有不错的质感
- 华为mate40系列外观确定,两个版本两种设计
- RX 6950?AMD还有顶级大招?
- 一条搞定所有接口,倍思闪速系列二拖三PD快充线评测