【有状态类一定是多例吗?无状态类一定是单例吗?】

有状态类一定是多例吗?无状态类一定是单例吗?

答案是否定的。有状态类和无状态类与单例/多例模式是正交概念,它们可以自由组合,具体如何设计取决于业务需求。下面详细分析:


1. 有状态类 ≠ 多例

有状态类可以是单例

  • 场景:当全局只需要一个实例,并且该实例需要维护某些状态时。
  • 例子
    • 全局计数器(单例 + 有状态):
      public class GlobalCounter {
          private static final GlobalCounter INSTANCE = new GlobalCounter();
          private int count = 0; // 可变状态
      
          private GlobalCounter() {}
      
          public static GlobalCounter getInstance() {
              return INSTANCE;
          }
      
          public synchronized int increment() {
              return ++count; // 需要同步
          }
      }
      
    • 应用配置管理器(单例 + 有状态):
      public class AppConfig {
          private static final AppConfig INSTANCE = new AppConfig();
          private String theme = "dark"; // 可变状态
      
          private AppConfig() {}
      
          public static AppConfig getInstance() {
              return INSTANCE;
          }
      
          public void setTheme(String theme) {
              this.theme = theme;
          }
      }
      
  • 关键点
    • 虽然是单例,但内部维护可变状态(如 counttheme)。
    • 由于是单例,多线程访问时需加锁(如 synchronized)。

有状态类也可以是多例

  • 场景:每个实例需要独立的状态(如用户会话、数据库连接)。
  • 例子
    • 用户会话管理(多例 + 有状态):
      public class UserSession {
          private final String userId; // 实例级状态
          private List<String> permissions;
      
          public UserSession(String userId) {
              this.userId = userId;
          }
      
          public void loadPermissions() {
              this.permissions = fetchFromDB(userId); // 初始化状态
          }
      }
      
    • 数据库连接池(多例 + 有状态):
      public class DatabaseConnection {
          private final String connectionId;
          private boolean isBusy = false; // 状态
      
          public DatabaseConnection(String id) {
              this.connectionId = id;
          }
      
          public void executeQuery(String sql) {
              this.isBusy = true;
              // ...
          }
      }
      
  • 关键点
    • 每个实例独立维护自己的状态(如 userIdisBusy)。
    • 多例模式下,状态隔离,无需全局锁(但实例内部仍需线程安全)。

2. 无状态类 ≠ 单例

无状态类可以是单例

  • 场景:工具类或全局服务,无需维护状态,且只需一个实例。
  • 例子
    • 数学工具类(单例 + 无状态):
      public class MathUtils {
          private static final MathUtils INSTANCE = new MathUtils();
      
          private MathUtils() {}
      
          public static MathUtils getInstance() {
              return INSTANCE;
          }
      
          public int add(int a, int b) { // 无状态,仅依赖参数
              return a + b;
          }
      }
      
    • 日志工具类(单例 + 无状态):
      public class Logger {
          private static final Logger INSTANCE = new Logger();
      
          private Logger() {}
      
          public static Logger getInstance() {
              return INSTANCE;
          }
      
          public void log(String message) { // 无状态
              System.out.println(message);
          }
      }
      
  • 关键点
    • 无状态类作为单例时,天然线程安全(因为没有共享可变数据)。
    • 通常直接用 static 方法(如 Math.max()),无需显式单例。

无状态类也可以是多例

  • 场景:虽然无状态,但需要多个实例(如线程池任务、策略模式)。
  • 例子
    • Runnable 任务(多例 + 无状态):
      public class CleanTask implements Runnable {
          @Override
          public void run() { // 无状态,仅依赖外部输入
              System.out.println("Cleaning...");
          }
      }
      
    • 策略模式中的策略(多例 + 无状态):
      public interface DiscountStrategy {
          double apply(double price); // 无状态,纯计算
      }
      
      public class HalfDiscount implements DiscountStrategy {
          @Override
          public double apply(double price) {
              return price * 0.5;
          }
      }
      
  • 关键点
    • 虽然类本身无状态,但可能通过多例实现不同行为(如不同折扣策略)。
    • 多例无状态类通常用于组合模式依赖注入(如 Spring Bean)。

3. 组合关系总结

类别单例多例
有状态类✅ 全局计数器、配置管理器✅ 用户会话、数据库连接
无状态类✅ 工具类(MathUtils✅ 策略模式、线程任务

4. 如何选择?

有状态类设计建议

  • 单例:当状态需要全局共享(如应用配置),但需注意线程安全。
  • 多例:当状态需要隔离(如用户会话、连接池)。

无状态类设计建议

  • 单例:工具类(如 StringUtils),避免重复创建。
  • 多例:需要灵活组合时(如策略模式)。

5. 经典误区

误区1:无状态类必须用单例

  • 实际上,无状态类可以是多例(如 Runnable),只是通常更省内存。

误区2:有状态类必须用多例

  • 单例有状态类很常见(如全局缓存),但需处理好并发。

误区3:静态方法 = 无状态单例

  • 静态方法本质是无状态的,但单例是对象生命周期管理策略,二者不同。

6. 总结

  • 有状态类可以单例(全局状态)或多例(独立状态)。
  • 无状态类可以单例(工具类)或多例(策略模式)。
  • 关键区别
    • 有状态类依赖内部可变数据。
    • 无状态类仅依赖输入参数。
  • 设计核心:根据业务需求选择 状态管理方式实例化策略
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值