掌握 Dart 的 sealed class(三)

168 阅读2分钟

面向对象设计原则(SOLID) 来看,Dart 中的 sealed class 是一个非常契合多项设计原则的工具。我们可以逐条分析它与 SOLID 原则的关系:

🔹 S - 单一职责原则(SRP)

每个类应该只有一个职责,且该职责应该完全封装在类中。

sealed class 强制你将一个有限状态系统拆分为多个子类,每个子类负责自己的逻辑(如状态、错误、响应等),符合 SRP:

sealed class NetworkResult {}

class Success extends NetworkResult {
  final String data;
  Success(this.data);
}

class Failure extends NetworkResult {
  final String message;
  Failure(this.message);
}

Success 只负责成功的结构,Failure 只负责失败的结构,职责单一,清晰分离。

🔹 O - 开闭原则(OCP)

对扩展开放,对修改封闭。

sealed class 可以通过新增子类来扩展系统,而不必修改已有逻辑。

// 想支持超时状态,只需要新增 Timeout:
class Timeout extends NetworkResult {}

✅ 不修改 Success / Failure 等已有子类,系统即可扩展,符合开闭原则。

🔹 L - 里氏替换原则(LSP)

子类对象必须能够替换父类对象使用。

sealed class 定义的是一种类型家族,你可以放心地将任一子类替换为父类使用。

void handle(NetworkResult result) {
  // 所有子类都可替换 NetworkResult 类型处理
}

✅ 所有子类(如 Success, Failure)都可以无缝用于 NetworkResult,满足 LSP。

🔹 I - 接口隔离原则(ISP)

不要强迫客户端依赖它们不使用的方法。

虽然 Dart 没有接口关键字,但 sealed class 的子类可以拥有各自方法和字段,不共享不必要的结构。

class Success extends NetworkResult {
  final String data;
  void logSuccess() {}
}

class Failure extends NetworkResult {
  final String error;
  void reportError() {}
}

✅ 不会让子类被强制实现无关的方法,各子类职责清晰,接口最小化。

🔹 D - 依赖倒置原则(DIP)

高层模块不应该依赖低层模块,二者都应该依赖抽象。

在实际架构中,使用 sealed class 作为抽象模型,高层业务代码依赖的是 sealed 的抽象,而不是具体实现:

void process(NetworkResult result) {
  switch (result) {
    case Success(:var data):
      print('Got $data');
      break;
    case Failure(:var message):
      print('Error: $message');
      break;
  }
}

✅ 业务逻辑依赖抽象类型 NetworkResult,而不是具体子类,符合依赖倒置。

✅ 总结

设计原则sealed class 是否契合理由
SRP每个子类职责单一
OCP新增子类即可扩展
LSP子类可以无缝替代父类使用
ISP子类仅实现自身需要的结构
DIP高层依赖抽象 sealed class 类型