组合模式的核心价值在于用统一Rule接口建模嵌套不确定的规则结构,使原子规则与组合规则可递归执行;通过工厂解析JSON/DLS构建树,显式栈避免栈溢出,并支持缓存优化性能。

理解组合模式在规则引擎中的核心价值
组合模式不是为了“套用设计模式”而存在,而是为了解决一类典型问题:当规则本身可以嵌套、分组、条件化,并且结构不确定(比如用户自定义的“所有条件都满足”“任意一个满足”“非此即彼”),又需要统一执行逻辑时,用树形结构建模最自然。Java 中不依赖框架也能实现——关键在于把“单个规则”和“规则容器”抽象成同一接口,让调用方无需区分叶子节点与分支节点。
定义统一的 Rule 接口与基础实现
先定义顶层行为契约:
Rule.java
boolean evaluate(Context context);
立即学习“Java免费学习笔记(深入)”;
然后提供两类实现:
-
原子规则(Leaf):如
EqualsRule("status", "active")、GreaterThanRule("age", 18),直接读取上下文字段并返回布尔结果; -
组合规则(Composite):如
AndRule(List<Rule> children)、OrRule(List<Rule> children)、NotRule(Rule inner),其evaluate()方法递归调用子规则,按逻辑聚合结果。
这样任意深度的嵌套表达式(如 AND(OR(A, B), NOT(C)))都能用对象树表示,且新增运算符只需加新 Composite 类,不修改原有逻辑。
支持动态构建与运行时解析
用户配置的 JSON 或 DSL 需要能转成 Rule 对象树。例如解析如下 JSON:
{ "type": "and", "children": [ { "type": "eq", "field": "role", "value": "admin" }, { "type": "or", "children": [ { "type": "gt", "field": "score", "value": 90 }, { "type": "lt", "field": "age", "value": 35 } ] } ] }
可写一个轻量 RuleParser,用工厂方法根据 type 创建对应 Rule 实例,对 children 字段递归调用自身。重点是:每个 Composite 构造时不校验子规则是否为空,允许空列表(默认 true 或 false 可配置),避免运行时报 NPE。
执行时避免栈溢出与提升性能
无限递归不等于无限制嵌套——真实场景中嵌套百层就可能触发 StackOverflowError。解决方法有二:
- 在
evaluate()中加入深度计数器,超过阈值(如 50 层)主动抛出RuleEvaluationException("max depth exceeded"); - 将递归改为显式栈(
Deque<RuleExecutionFrame>),每个帧记录当前 Rule 和待处理子索引,手动控制遍历过程,内存可控且便于调试。
另外,高频规则建议支持缓存:对纯函数型原子规则(不依赖外部状态),可封装为 CachedRule,内部用 WeakHashMap<ContextKey, Boolean> 缓存最近结果,ContextKey 可基于字段哈希生成。


















