1. Primitive Obsession(基本类型偏执)中何时应该用值对象替代散落的字符串/数字参数?
说明 Primitive Obsession(基本类型偏执)反模式,以及何时应该用值对象替代散落的字符串/数字参数?
- 基本类型偏执的定义
- 值对象的引入时机
- 类型安全与行为内聚
Primitive Obsession 指用基本类型(String/int/boolean)表达领域概念大量散落在代码中,问题在于:无类型安全(如把"金额"和"数量"都当 int 混用)、重复校验逻辑(到处校验字符串格式)、语义不清晰(天数与秒数难区分)且难以承载行为。当某个基本类型在多个地方被反复校验、转换或承载业务规则时,应引入值对象(Value Object):把数值/字符串 + 其校验与行为封装成一个类,获得类型安全、单一职责与行为内聚。例如用 Money 类封装金额与币种,用 Quantity 类封装数量与单位,用 Email 类封装格式校验。
值对象是"以类型系统表达领域语义"。判断标准是"重复出现的校验与行为"或"类型混淆风险"。引入值对象可提升可读性、减少重复、增加类型安全,但不要过度封装简单场景。
// 值对象:把金额与币种封装,避免 int/float 混用
public final class Money {
private final BigDecimal amount;
private final String currency;
public Money(BigDecimal amount, String currency) {
if (amount == null || amount.signum() < 0) {
throw new IllegalArgumentException("amount must be non-negative");
}
this.amount = amount;
this.currency = currency;
}
public Money add(Money other) {
if (!currency.equals(other.currency)) {
throw new IllegalArgumentException("currency mismatch");
}
return new Money(amount.add(other.amount), currency);
}
// equals/hashCode based on amount and currency
}