Introduce Special Case 是什么
为「特殊值」建立可复用的对象:未知客户、缺失配置、空集合。把判空与兜底逻辑收进特例对象后,调用方不再遍地形如 if (x == null),默认行为也集中在一处定义。空对象模式(Null Object)是它最常见的形态;《重构》里把它归入简化条件表达式的一组手法。
基本信息
| 场景 | 到处判 null、缺省值,默认行为在多处重复 |
|---|---|
| 形态 | Null Object、Unknown Customer、Empty Collection |
| 收益 | 调用方不再遍地形如 if (x == null) |
| 前提 | 默认行为是确定的、可命名的业务语义 |
典型用法
- 未登录用户用一个匿名用户对象承载默认权限与默认昵称
- 缺失配置用带默认值的配置对象替代 null,避免每个读取点判空
- 空集合用迭代器模式的空对象,循环代码不必特判
- 上游系统查不到记录时返回「未知实体」,展示层直接显示占位文案
- 把散落在各处的默认值集中到特例对象的构造里,改默认值只改一处
Java 示例
Java 示例
interface Customer {
String name();
BillingPlan plan();
boolean isUnknown();
}
class UnknownCustomer implements Customer {
@Override public String name() { return "occupant"; }
@Override public BillingPlan plan() { return BillingPlan.basic(); }
@Override public boolean isUnknown() { return true; }
}
// 调用方:不再需要判空
String who = site.customer().name();适用与不适用
| 情况 | 处理 | 原因 |
|---|---|---|
| 缺失但有明确默认行为 | 特例对象 | 把默认语义显式化 |
| 缺失即代表异常 | 抛出异常 | 静默兜底会掩盖故障 |
| 特例需要承载状态变化 | 慎重使用 | 共享实例可能被意外改坏 |
| 默认行为频繁变化 | 先提取默认值 | 避免特例对象频繁改动 |
特例对象应当不可变,并且通常是单例:它会被很多调用点共享,一旦有某个调用方改了它的状态,影响面不可控。
用特例对象吞掉真实错误是常见陷阱:把「查不到」和「下游超时」都返回同一个未知对象,故障就再也不会被上报。先分清「缺失」与「失败」,只对前者使用特例。