目录
常用的设计模式
/  

常用的设计模式

常用的设计模式

单例模式

饿汉式

  • 在加载时就创建并初始化单例实例
  • 线程安全,简单容易实现
  • 可能会造成资源浪费,因为实例在应用程序启动时就被创建
public class EagerSingleton {
  private static final EagerSingleton instance = new EagerSingleton()l
  
    private EagerSingleton() {
      // 私有构造函数
    }
    public static EagerSingleton getInstance() {
      return instance;
    }
}

懒汉式

  • 在第一次使用时才会创建实例
  • 可以实现延迟加载,节约资源
  • 需要考虑线程安全性,可能需要加锁来确保多线程环境下的安全访问
public class LazySingleton {
  private static LazySingleton instance;
  
  private LazySingleton() {
    // 私有构造函数
  }
  
  public static synchronized LazySingleton getInstance() {
    if (instance == null) {
      instance = new LazySingleton();
    }
    return instance;
  }
  
}

双重检查锁定单例模式

  • 结合了懒加载和线程安全,确保在多线程环境下只会创建一个实例
  • 通过双重检查来减少锁的使用,提高性能
  • 在早期的Java版本中可能存在指令重排序问题,需要小心处理。

指令重排序:指令重排序是现代处理器为了提高性能锁采取的一种优化手段。在计算机执行指令时,处理器可能会对指令进行重排序,以充分利用处理器资源并提高执行效率。然后,指令重排序可能会导致程序的行为与预期不符,特别是在多线程环境下。

在单例模式中,如果不小心处理,指令重排序可能会导致单例对象在多线程环境下出现问题。以双重检查锁定单例模式为例,如果不使用 volatile 关键字修饰单例对象,会存在指令重排序的风险。

以下是指令重排序可能引发的问题:

  • 初始化顺序问题:如果在多线程环境下,一个线程在第一次检查实例是否为 null 时发现它不为 null,但实际上这个实例还未完成初始化,这时另一个线程可能会拿到一个尚未完全初始化的实例
  • 可见性问题:指令重排序可能会导致对共享变量的修改在不同线程中的可见性问题,一个线程修改了共享变量的值,但另一个线程看不到这个修改。

为了解决指令重排序带来的问题,可以通过一下方式来保证线程安全:

  • 在需要的地方使用 volatile 关键字,确保变量的可见性。
  • 使用同步块或锁来保证代码的顺序执行。
  • 使用线程安全的数据结构或工具类。
public class DoubleCheckedSingleton {
  
  // 保证内存可见性
  private static volatile DoubleCheckedSingleton instance;
  
  private DoubleCheckedSingleton() {
    // 私有构造函数
  }
  public static DoubleCheckedSingleton getInstance() {
    if (instance == null) {
      synchronized (DoubleCheckedSingleton.class) {
        if (instance == null) {
          instance = new DoubleCheckedSingleton();
        }
      }
    }
    return instance;
  }
}

静态内部类单例模式

  • 利用静态内部类的特性实现延迟加载和线程安全
  • 当第一次加载静态内部类时才会初始化单例实例
  • 线程安全,代码简洁。
public class StaticInnerSingleton {
  private StaticInnerSingleton() {
    // 私有构造函数
  }
  
  private static class SingletonHolder {
    private static final StaticInnerSingleton instance = new StaticInnerSingleton();
  }
  public static StaticInnerSingleton getInstance() {
    return SingletonHolder.instance;
  }
}

枚举单例模式

  • 利用枚举类型的特性实现单例模式
  • 线程安全,防止反射和序列化攻击
  • 简单明了,推荐使用
public enum EnumSingleton {
    INSTANCE;

    // 可以添加其他方法或属性
}

工厂模式

策略模式

模板方法模式

适配器模式

责任链模式


标题:常用的设计模式
作者:gitsilence
地址:https://blog.lacknb.cn/articles/2024/03/05/1709623547440.html