领域战术核心:解密规格模式(Specification)的规约链设计
在领域驱动设计(DDD)的战术装配中,编写干净、高表达力的业务校验规则是一大挑战。如果把诸如“用户是否具备金牌会员资格且最近 30 天无恶意退款”这类复杂的组合判定直接写在聚合根中,会导致实体内部充斥大量的业务校验噪音,难以复用且无法进行干净的单元测试。
为了解决业务规则的复用与解耦,DDD 引入了**规格模式(Specification Pattern)**。在此基础之上,通过应用**组合模式(Composite Pattern)**,我们可以将多个单一规格灵活地串联为一条并发安全的**规约链(Specification Chain)**。
本文将系统拆解规格模式的高级组合架构、And/Or/Not 规约链的逻辑流转、以及标准的 Java 充血代码实现。
一、 核心范式:规约链的组合逻辑算子
规约链通过在基类规格接口中声明逻辑组合算子(Logical Operators),实现了对单一规则的无限级联装配:
| 逻辑组合算子 | 物理语义描述 | 数学逻辑表达式 | 典型业务场景 |
|---|---|---|---|
and(other) | **与**逻辑。两个规格必须同时满足。 | (SpecA(x) land SpecB(x)) | 如:账户处于“激活”状态 **且** 余额大于转账金额。 |
or(other) | **或**逻辑。满足其中任意一个规格即可。 | (SpecA(x) lor SpecB(x)) | 如:用户是“新注册用户” **或** 持有“专属代金券”。 |
not() | **非**逻辑。对当前规格的判定结果取反。 | ( eg SpecA(x)) | 如:订单状态 **不处于** “已取消”状态。 |
二、 组合规约链的运行判定拓扑
当我们要判定一个订单是否符合“高级促销活动规格”(即:[金额超百元 并且 不是特价品] 或者 是新用户首单)时,规约链的流转判定拓扑如下:
[ 待校验实体: SalesOrder ]
│
▼ 1. 注入规约链入口
[ OrSpecification (根节点) ]
│
┌───────────────────────┴───────────────────────┐
(左节点判定) (右节点判定)
▼ ▼
[ AndSpecification ] [ NewUserSpec ]
│ (与运算) │
├─ 2a. [ Over100AmountSpec ] ──(True) ├─ 2b. (False)
└─ 3a. [ NotSpec (SpecialItemSpec) ] ──(True) │
│ │
▼ ▼
结果为 True 结果为 False
│ │
└───────────────────────┬───────────────────────┘
│
▼ 4. 执行 OR 运算: True ∨ False = True
[ 5. 返回结果: 校验通过 ]
---三、 代码实战:构建并发安全的级联规格链
以下代码展示了如何利用组合设计模式,编写高复用性、并发安全的抽象规格基类与具体实现:
1. 领域层:抽象规格基类与组合逻辑算子(Domain Layer)
package com.company.sales.domain.specification;
/**
* 抽象规格基类(支持级联 And/Or/Not 装配)
*/
public abstract class AbstractSpecification<T> {
public abstract boolean isSatisfiedBy(T candidate);
/**
* 逻辑“与”组合
*/
public AbstractSpecification<T> and(AbstractSpecification<T> other) {
return new AndSpecification<>(this, other);
}
/**
* 逻辑“或”组合
*/
public AbstractSpecification<T> or(AbstractSpecification<T> other) {
return new OrSpecification<>(this, other);
}
/**
* 逻辑“非”取反
*/
public AbstractSpecification<T> not() {
return new NotSpecification<>(this);
}
}
2. 领域层:具体的逻辑运算节点实现(Composite Nodes)
package com.company.sales.domain.specification;
public class AndSpecification<T> extends AbstractSpecification<T> {
private final AbstractSpecification<T> left;
private final AbstractSpecification<T> right;
public AndSpecification(AbstractSpecification<T> left, AbstractSpecification<T> right) {
this.left = left;
this.right = right;
}
@Override
public boolean isSatisfiedBy(T candidate) {
return left.isSatisfiedBy(candidate) && right.isSatisfiedBy(candidate);
}
}
3. 领域层:具体业务规格与用例编配
package com.company.sales.domain.specification;
import com.company.sales.domain.model.SalesOrder;
/**
* 业务规格一:订单金额超百元规格
*/
public class Over100AmountSpec extends AbstractSpecification<SalesOrder> {
@Override
public boolean isSatisfiedBy(SalesOrder order) {
return order.getTotalAmount() > 100.0;
}
}
package com.company.sales.application.service;
import com.company.sales.domain.model.SalesOrder;
import com.company.sales.domain.specification.*;
public class PromotionApplicationService {
public void applyPromotion(SalesOrder order) {
// 1. 声明单一规格
AbstractSpecification<SalesOrder> over100Spec = new Over100AmountSpec();
AbstractSpecification<SalesOrder> specialItemSpec = new SpecialItemSpec();
AbstractSpecification<SalesOrder> newUserSpec = new NewUserSpec();
// 2. 级联装配复杂的规约链:[金额超百元 并且 不是特价品] 或者 是新用户首单
AbstractSpecification<SalesOrder> finalPromoSpec = over100Spec
.and(specialItemSpec.not())
.or(newUserSpec);
// 3. 执行一键校验,彻底隔离复杂的 if-else
if (finalPromoSpec.isSatisfiedBy(order)) {
System.out.println("[Promotion] 订单符合促销规格,成功激活折扣!");
} else {
System.out.println("[Promotion] 订单不符合促销规则。");
}
}
}
---四、 总结
规格模式(Specification)的规约链设计,是解决微服务系统中规则泛滥与逻辑缠绕的“分流过滤器”。
It 通过**基于组合模式的 And/Or/Not 面向对象包装,将细粒度的校验规则剥离为独立、可测试的值对象,杜绝了聚合根内部大面积 if-else 的堆砌;并依靠链式调用的高可读性声明,达成了业务语言(Ubiquitous Language)与底层校验代码的高一致度对齐**。掌握这套规约链装配方法与组合设计模式,是进行复杂企业级校验系统架构设计、编写优雅 DDD 战术代码 of 核心看家本领!
本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。



暂无评论
还没有人评论过本文,快来发表你的高见吧!