解释器模式(Interpreter Pattern)是一种行为设计模式,它定义了一个语言的文法,并且建立一个解释器来解释该语言中的句子。这种模式通常用于需要解释执行特定领域语言的场景,将复杂的业务规则表示为一个语法树。
// 抽象表达式
public interface Expression {
boolean interpret(Map<String, Boolean> context);
}
// 终结符表达式
public class VariableExpression implements Expression {
private final String name;
public VariableExpression(String name) {
this.name = name;
}
@Override
public boolean interpret(Map<String, Boolean> context) {
return context.getOrDefault(name, false);
}
}
// 非终结符表达式 - AND
public class AndExpression implements Expression {
private final Expression expr1;
private final Expression expr2;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(Map<String, Boolean> context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
// 使用示例
public class Client {
public static void main(String[] args) {
// 构建表达式:(A AND B)
Expression expr = new AndExpression(
new VariableExpression("A"),
new VariableExpression("B")
);
Map<String, Boolean> context = new HashMap<>();
context.put("A", true);
context.put("B", false);
System.out.println(expr.interpret(context)); // 输出 false
}
}
// 规则引擎核心类
public class RuleEngine {
private final Map<String, Expression> ruleCache = new ConcurrentHashMap<>();
public boolean evaluate(String ruleExpression, Map<String, Object> context) {
Expression expression = ruleCache.computeIfAbsent(ruleExpression,
expr -> parseExpression(expr));
return expression.interpret(context);
}
private Expression parseExpression(String expression) {
// 使用ANTLR等解析器生成语法树
// 转换为解释器模式的表达式对象
// 这里简化实现
if (expression.contains("AND")) {
String[] parts = expression.split(" AND ");
return new AndExpression(parseExpression(parts[0]), parseExpression(parts[1]));
}
// 其他规则解析...
return new VariableExpression(expression);
}
}
在阿里电商平台的促销规则系统中,我们使用解释器模式实现复杂的促销条件判断:
典型促销规则示例:
(VIP=true) AND (购物金额>1000)
(商品类别='电子产品') OR (促销活动='双十一')
在字节跳动的广告投放系统中,我们使用解释器模式实现广告定向投放条件判断:
解决方案:
在电商风控系统中,需要实时处理海量规则判断请求,设计要点包括:
public class HighPerfRuleEngine {
private final RuleCache ruleCache; // 分布式缓存
private final RuleParser ruleParser;
private final ExecutorService executor;
// 带超时的并行解释
public boolean evaluateParallel(String ruleId, Map<String, Object> context,
long timeout, TimeUnit unit) {
Expression expression = ruleCache.get(ruleId);
if (expression == null) {
expression = ruleParser.parse(ruleId);
ruleCache.put(ruleId, expression);
}
Future<Boolean> future = executor.submit(() -> expression.interpret(context));
try {
return future.get(timeout, unit);
} catch (TimeoutException e) {
future.cancel(true);
throw new RuleTimeoutException();
} catch (Exception e) {
throw new RuleExecutionException(e);
}
}
}
关键问题解决:
public class VersionedRuleCache {
private final Cache<String, VersionedExpression> cache;
public Expression get(String ruleId, int version) {
VersionedExpression ve = cache.get(ruleId);
if (ve == null || ve.getVersion() < version) {
return null; // 需要重新加载
}
return ve.getExpression();
}
}
public class DistributedCompiler {
private final CompilerService[] compilerNodes;
private final AtomicInteger counter = new AtomicInteger();
public Expression compile(String expression) {
// 轮询选择编译节点
int index = counter.getAndIncrement() % compilerNodes.length;
return compilerNodes[index].compile(expression);
}
}
完整解决方案:
public class DistributedRuleEngine {
private final RuleRepository ruleRepository;
private final VersionedRuleCache ruleCache;
private final DistributedCompiler compiler;
private final ExecutorService executor;
public RuleEvaluationResult evaluate(String ruleId, Map<String, Object> context) {
// 1. 获取规则元数据
RuleMeta meta = ruleRepository.getRuleMeta(ruleId);
// 2. 尝试从缓存获取
Expression expression = ruleCache.get(ruleId, meta.getVersion());
// 3. 缓存未命中则编译
if (expression == null) {
String ruleExpression = ruleRepository.getRuleExpression(ruleId);
expression = compiler.compile(ruleExpression);
ruleCache.put(ruleId, expression, meta.getVersion());
}
// 4. 并行执行带超时
Future<Boolean> future = executor.submit(() -> expression.interpret(context));
try {
boolean result = future.get(meta.getTimeout(), TimeUnit.MILLISECONDS);
return new RuleEvaluationResult(result, meta.getVersion());
} catch (TimeoutException e) {
future.cancel(true);
throw new RuleTimeoutException(ruleId);
}
}
}
解决方案:
在金融风控系统中,面对成百上千的业务规则时,传统解释器模式会导致类数量激增。以下是综合解决方案:
设计模式结合:
public interface ExpressionVisitor<T> {
T visit(AndExpression expr);
T visit(OrExpression expr);
// 其他表达式类型...
}
public class InterpretVisitor implements ExpressionVisitor<Boolean> {
private final Map<String, Object> context;
public Boolean visit(AndExpression expr) {
return expr.getLeft().accept(this) && expr.getRight().accept(this);
}
// 其他visit方法...
}
DSL优化:
public class RuleDSL {
public static Expression rule(String dsl) {
// 解析DSL生成表达式树
}
}
// 使用示例
Expression expr = RuleDSL.rule("(A > 100) AND (B < 50)");
元编程技术:
public class DynamicExpressionBuilder {
public static Expression buildExpression(String operator,
Expression left,
Expression right) {
// 使用ASM或Javassist动态生成类
}
}
完整优化方案:
public class OptimizedRuleEngine {
private final ExpressionBuilder expressionBuilder;
private final ExpressionOptimizer optimizer;
public Expression compile(String rule) {
// 1. 解析为抽象语法树
ASTNode ast = parseToAST(rule);
// 2. 转换为优化后的表达式树
Expression expr = astToExpression(ast);
// 3. 应用优化规则
return optimizer.optimize(expr);
}
private Expression astToExpression(ASTNode node) {
if (node.isLeaf()) {
return expressionBuilder.buildLeaf(node);
} else {
Expression left = astToExpression(node.getLeft());
Expression right = astToExpression(node.getRight());
return expressionBuilder.buildNode(node.getOperator(), left, right);
}
}
}
// 表达式构建器接口
public interface ExpressionBuilder {
Expression buildLeaf(ASTNode node);
Expression buildNode(String operator, Expression left, Expression right);
}
解释器模式是处理领域特定语言的强大工具,在阿里、字节等大厂的复杂业务系统中有着重要应用。掌握解释器模式需要:
在实际工程实践中,解释器模式通常需要结合: