java23种设计模式-解释器模式

解释器模式(Interpreter Pattern)学习笔记


编程相关书籍分享:https://blog.csdn.net/weixin_47763579/article/details/145855793

DeepSeek使用技巧pdf资料分享:https://blog.csdn.net/weixin_47763579/article/details/145884039


1. 模式定义

行为型设计模式,给定一个语言,定义其文法的一种表示,并定义一个解释器,用于解释语言中的句子。通过构建语法树来实现特定领域语言的解释执行。

2. 适用场景

✅ 需要解释执行特定领域语言

✅ 文法规则相对稳定且易于扩展

✅ 需要频繁解释简单语法结构

✅ 不追求高效执行效率的场景

✅ 实现SQL解析、正则表达式引擎等

3. 模式结构

contains <<interface>> AbstractExpression +interpret(context: Context) : Object TerminalExpression +interpret(context: Context) : Object NonterminalExpression -expressions: List +interpret(context: Context) : Object Context -variables: Map +getVariable(name: String) : Object +setVariable(name: String, value: Object) Client +buildExpressionTree() : AbstractExpression

4. 核心角色

角色 说明
AbstractExpression 抽象表达式:声明解释操作的接口
TerminalExpression 终结符表达式:实现与文法中的终结符相关的解释操作
NonterminalExpression 非终结符表达式:维护包含其他表达式的结构,实现文法规则的组合解释逻辑
Context 上下文:包含解释器需要的全局信息
Client 客户端:构建语法树并调用解释方法

5. 代码示例

5.1 数学表达式解析器

java 复制代码
// 上下文(存储变量值)
class MathContext {
    private Map<String, Integer> variables = new HashMap<>();
    
    public void setVariable(String name, int value) {
        variables.put(name, value);
    }
    
    public int getVariable(String name) {
        return variables.getOrDefault(name, 0);
    }
}

// 抽象表达式
interface MathExpression {
    int interpret(MathContext context);
}

// 终结符表达式 - 数字
class Number implements MathExpression {
    private int number;
    
    public Number(int number) {
        this.number = number;
    }
    
    public int interpret(MathContext context) {
        return number;
    }
}

// 终结符表达式 - 变量
class Variable implements MathExpression {
    private String name;
    
    public Variable(String name) {
        this.name = name;
    }
    
    public int interpret(MathContext context) {
        return context.getVariable(name);
    }
}

// 非终结符表达式 - 加法
class Add implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public Add(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) + right.interpret(context);
    }
}

// 非终结符表达式 - 减法
class Subtract implements MathExpression {
    private MathExpression left;
    private MathExpression right;
    
    public Subtract(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) - right.interpret(context);
    }
}

// 客户端
public class Client {
    public static void main(String[] args) {
        // 构建表达式:a + (b - 10)
        MathContext context = new MathContext();
        context.setVariable("a", 20);
        context.setVariable("b", 30);
        
        MathExpression expression = new Add(
            new Variable("a"),
            new Subtract(
                new Variable("b"),
                new Number(10)
            )
        );
        
        int result = expression.interpret(context);
        System.out.println("计算结果: " + result); // 输出:20 + (30-10) = 40
    }
}

6. 模式变种

6.1 支持优先级运算

java 复制代码
class Multiply extends BinaryExpression {
    public Multiply(MathExpression left, MathExpression right) {
        super(left, right);
    }
    
    public int interpret(MathContext context) {
        return left.interpret(context) * right.interpret(context);
    }
}

class Power extends BinaryExpression {
    public Power(MathExpression left, MathExpression right) {
        super(left, right);
    }
    
    public int interpret(MathContext context) {
        return (int) Math.pow(
            left.interpret(context),
            right.interpret(context)
        );
    }
}

7. 优缺点分析

✔️ 优点

  • 易于扩展新的文法规则
  • 实现语言解释器的标准模式
  • 将语法解析与表达式求值分离
  • 符合单一职责原则

缺点

  • 复杂文法难以维护(类数量爆炸)
  • 执行效率较低(递归调用多)
  • 应用场景有限
  • 难以处理左递归文法

8. 相关模式对比

模式 目的 关键区别
组合模式 树形结构处理 解释器通常使用组合模式构建语法树
访问者模式 分离数据结构与操作 解释器模式侧重语法解析,访问者侧重数据操作
策略模式 封装算法族 解释器模式处理语言解析,策略处理算法选择

9. 实际应用案例

  • Java正则表达式引擎(Pattern/Matcher)
  • Spring表达式语言(SpEL)
  • SQL解析器实现
  • 金融领域的业务规则引擎
  • 编译器语法分析阶段
  • XML文档解析器
  • 数学公式计算器

10. 最佳实践建议

  1. 使用组合模式构建语法树
java 复制代码
abstract class BinaryExpression implements MathExpression {
    protected MathExpression left;
    protected MathExpression right;
    
    public BinaryExpression(MathExpression left, MathExpression right) {
        this.left = left;
        this.right = right;
    }
}
  1. 结合工厂模式创建表达式
java 复制代码
class ExpressionFactory {
    public static MathExpression create(String expr) {
        // 解析表达式字符串,构建语法树
        // 示例:解析 "a + b * 3"
        return new Add(
            new Variable("a"),
            new Multiply(
                new Variable("b"),
                new Number(3)
            )
        );
    }
}
  1. 实现上下文缓存优化
java 复制代码
class CachedExpression implements MathExpression {
    private MathExpression expression;
    private Map<MathContext, Integer> cache = new WeakHashMap<>();
    
    public CachedExpression(MathExpression expression) {
        this.expression = expression;
    }
    
    public int interpret(MathContext context) {
        return cache.computeIfAbsent(context, 
            ctx -> expression.interpret(ctx));
    }
}
  1. 使用访问者模式实现多种操作
java 复制代码
interface ExpressionVisitor {
    void visit(Number number);
    void visit(Variable variable);
    void visit(Add add);
    void visit(Subtract subtract);
}

class PrintVisitor implements ExpressionVisitor {
    public void visit(Number number) {
        System.out.print(number.value);
    }
    
    public void visit(Variable variable) {
        System.out.print(variable.name);
    }
    
    public void visit(Add add) {
        add.left.accept(this);
        System.out.print(" + ");
        add.right.accept(this);
    }
    // 其他visit方法...
}

📜 设计原则体现

  1. 单一职责原则:每个表达式类只处理特定语法元素
  2. 开闭原则:新增表达式类型无需修改现有代码
  3. 组合优于继承:通过组合方式构建复杂表达式

11. 扩展应用(SQL条件解析)

java 复制代码
// 条件表达式接口
interface Condition {
    boolean interpret(Map<String, Object> row);
}

// 等于条件
class Equals implements Condition {
    private String column;
    private Object value;
    
    public Equals(String column, Object value) {
        this.column = column;
        this.value = value;
    }
    
    public boolean interpret(Map<String, Object> row) {
        return value.equals(row.get(column));
    }
}

// AND条件
class And implements Condition {
    private Condition left;
    private Condition right;
    
    public And(Condition left, Condition right) {
        this.left = left;
        this.right = right;
    }
    
    public boolean interpret(Map<String, Object> row) {
        return left.interpret(row) && right.interpret(row);
    }
}

// 使用示例
Condition condition = new And(
    new Equals("status", "active"),
    new Or(
        new Equals("age", 25),
        new GreaterThan("score", 80)
    )
);

Map<String, Object> row = new HashMap<>();
row.put("status", "active");
row.put("age", 26);
row.put("score", 85);

boolean result = condition.interpret(row); // 返回true

通过解释器模式,可以实现灵活的语言解释功能,特别适合需要自定义领域特定语言(DSL)的场景。该模式在规则引擎、查询语言解析和公式计算等领域应用广泛,是处理语法解析问题的经典解决方案。

相关推荐
陈小桔1 小时前
idea中重新加载所有maven项目失败,但maven compile成功
java·maven
小学鸡!1 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
xiaogg36781 小时前
阿里云k8s1.33部署yaml和dockerfile配置文件
java·linux·kubernetes
逆光的July1 小时前
Hikari连接池
java
微风粼粼2 小时前
eclipse 导入javaweb项目,以及配置教程(傻瓜式教学)
java·ide·eclipse
番茄Salad2 小时前
Spring Boot临时解决循环依赖注入问题
java·spring boot·spring cloud
天若有情6732 小时前
Spring MVC文件上传与下载全面详解:从原理到实战
java·spring·mvc·springmvc·javaee·multipart
祈祷苍天赐我java之术2 小时前
Redis 数据类型与使用场景
java·开发语言·前端·redis·分布式·spring·bootstrap
Olrookie3 小时前
若依前后端分离版学习笔记(二十)——实现滑块验证码(vue3)
java·前端·笔记·后端·学习·vue·ruoyi
倚栏听风雨4 小时前
java.lang.SecurityException异常
java