广告
您当前的位置: 首页 >  技术 >  编程开发

领域战术核心:解密规格模式(Specification)的规约链设计

作者:CoderWang 时间:2026-07-07 阅读数:1人阅读

在领域驱动设计(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 核心看家本领!

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。

评论交流 (0)

正在加载评论...
头像

CoderWang

当你还撑不起你的梦想时,就要去奋斗。如果缘分安排我们相遇,请不要让她擦肩和过。我们一起奋斗!

微信