找回密码
 立即注册
首页 业界区 业界 【解释器设计模式详解】C/Java/Go/JS/TS/Python不同语言 ...

【解释器设计模式详解】C/Java/Go/JS/TS/Python不同语言实现

唐嘉懿 2025-6-6 09:41:29
简介

解释器模式(Interpreter Pattern)是一种行为型设计模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式常被用在 SQL 解析、符号处理引擎等。
解释器模式常用于对简单语言的编译或分析实例中,为了掌握好它的结构与实现,必须先了解编译原理中的“文法、句子、语法树”等相关概念。
 
作用


  • 可扩展性比较好,灵活,增加了新的解释表达式的方式,易于实现简单文法。
  • 在语法树中的每个表达式节点类都是相似的,所以实现其文法较为容易。
 
实现步骤


  • 创建抽象表达式接口(Expression),各种表达式都要实现该接口。
  • 分别创建最终表达式和非最终表达式。最终表达式(这里是VarExpression)没有子级,直接解释表达式。非最终表达式(这里是AddExpression和SubtractExpression)是维护子表达式的容器,并将解释请求转发给这些表达式。
  • 创建上下文环境类(这里是Context),用来表达式求值时构建执行环境。
  • 客户端调用时先建立执行上下文环境,然后声明变量,再进行计算。
 
UML

1.png

 
 
Java代码

 
抽象表达式接口
  1. // Expression.java 抽象表达式接口,根据业务场景规范表达式
  2. public interface Expression {
  3.   public int interpret(Context context);
  4. }
复制代码
 
 
具体表达式实现

 
  1. // AddExpression.java 具体表达式,实现了抽象表达式接口
  2. public class AddExpression implements Expression {
  3.     private Expression exprOne = null;
  4.     private Expression exprTwo = null;
  5.     public AddExpression(Expression exprOne, Expression exprTwo) {
  6.         this.exprOne = exprOne;
  7.         this.exprTwo = exprTwo;
  8.     }
  9.     // 覆盖表达式,执行context对象
  10.     @Override
  11.     public int interpret(Context context) {
  12.         System.out.println(this.getClass().getName() + "::interpret() [context = " + context.getClass().getName() + "]");
  13.         return exprOne.interpret(context) + exprTwo.interpret(context);
  14.     }
  15. }
  16. // SubtractExpression.java 具体表达式,实现了抽象表达式接口
  17. public class SubtractExpression implements Expression {
  18.   private Expression exprOne = null;
  19.   private Expression exprTwo = null;
  20.   public SubtractExpression(Expression exprOne, Expression exprTwo) {
  21.     this.exprOne = exprOne;
  22.     this.exprTwo = exprTwo;
  23.   }
  24.   // 覆盖表达式,执行context对象
  25.   @Override
  26.   public int interpret(Context context) {
  27.     System.out.println(this.getClass().getName() + "::interpret() [context = " + context.getClass().getName() + "]");
  28.     return exprOne.interpret(context) - exprTwo.interpret(context);
  29.   }
  30. }
  31. // VarExpression.java 变量表达式,或者叫终端表达式,其他表达式求值时通过层层追溯最后指向这里
  32. // 变量与执行环境的Key对应,最终会通过key获取传入的值
  33. public class VarExpression implements Expression {
  34.   private String key;
  35.   public VarExpression(String key) {
  36.     this.key = key;
  37.   }
  38.   @Override
  39.   // 覆盖表达式,根据key获取变量
  40.   public int interpret(Context context) {
  41.     return context.get(key);
  42.   }
  43. }
复制代码
 
执行环境类

 
  1. // Context.java 构建可执行环境上下文
  2. public class Context {
  3.    private Map<String, Integer> map = new HashMap<>();
  4.    public Context(String key, int value) {
  5.       this.add(key, value);
  6.    }
  7.    public Context() {
  8.    }
  9.    public void add(String key, int value) {
  10.       map.put(key, value);
  11.    }
  12.    public int get(String key) {
  13.       return map.get(key);
  14.    }
  15. }
  16. // Application.java 调用程序,组织各种解释器
  17.     /*
  18.      * 解释器模式先构建执行上下文Context,然后构建一个最终的获取值的表达式VarExpression,这就构成了含上下文和变量-值的基本环境。
  19.      * 再将基本环境放到工具表达式里AddExpression或SubtractExpreesion进行计算,最终得到结果。
  20.      */
  21.    // 构建两个数相加的例子
  22.    public static int addTwo(int one, int two) {
  23.       // 构建执行上下文环境
  24.       Context context = new Context();
  25.       context.add("one", one);
  26.       context.add("two", two);
  27.       // 构建表达式
  28.       VarExpression varOne = new VarExpression("one");
  29.       VarExpression varTwo = new VarExpression("two");
  30.       // 再构建变量来进行计算,看起来啰嗦,但这样构建多种不同表达式计算就变得简单
  31.       Expression result = new AddExpression(varOne, varTwo);
  32.       return result.interpret(context);
  33.    }
  34.    // 构建连加计算的例子
  35.    public static int addMore(int... numbers) {
  36.       if (numbers.length <= 1) {
  37.          return numbers[0];
  38.       }
  39.       Context context = new Context();
  40.       // 构建执行环境
  41.       for (int num : numbers) {
  42.          context.add("num" + num, num);
  43.       }
  44.       // 先取出前两个作为计算基础
  45.       VarExpression varOne = new VarExpression("num" + numbers[0]);
  46.       VarExpression varTwo = new VarExpression("num" + numbers[1]);
  47.       // 再构建表达式,先赋值前两个
  48.       Expression expression = new AddExpression(varOne, varTwo);
  49.       // 如果只有两个数则直接返回计算结果
  50.       if (numbers.length == 2) {
  51.          return expression.interpret(context);
  52.       }
  53.       // 如果数量超过两个则累加表达式再求值
  54.       for (int i = 2; i < numbers.length; i++) {
  55.          Expression nextExpression = new VarExpression("num" + numbers[i]);
  56.          // 表达式不断累加
  57.          expression = new AddExpression(expression, nextExpression);
  58.       }
  59.       return expression.interpret(context);
  60.    }
  61.    // 计算前两个数相加,再减去后一个数的计算例子
  62.    public static int addAndSubtract(int one, int two, int three) {
  63.       // 构建执行上下文环境,有3个可操作的域
  64.       Context context = new Context();
  65.       context.add("one", one);
  66.       context.add("two", two);
  67.       context.add("three", three);
  68.       // 构建表达式,有3个变量
  69.       VarExpression varOne = new VarExpression("one");
  70.       VarExpression varTwo = new VarExpression("two");
  71.       VarExpression varThree = new VarExpression("three");
  72.       // 再构建计算步骤,前两个用加法
  73.       Expression result = new AddExpression(varOne, varTwo);
  74.       result = new SubtractExpression(result, varThree);
  75.       // 第3个用减法
  76.       return result.interpret(context);
  77.    }
复制代码
 
执行环境类

 
  1.     /**
  2.      * 解释器模式实现了一个表达式接口,该接口可以解释一个特定的上下文的变量和语句。
  3.      * 也就是先定义上下文,然后定义变量,再使用表达式进行求值。相当可以构造一个简单的语法解析器。
  4.      */
  5.     int result1 = Application.addTwo(1, 2);
  6.     System.out.println("result1: " + result1);
  7.     int result2 = Application.addMore(1, 2, 3, 4, 5);
  8.     System.out.println("result2: " + result2);
  9.     int result3 = Application.addAndSubtract(3, 4, 5);
  10.     System.out.println("result3: " + result3);
复制代码
 
测试调用
  1. // Expression.go 抽象表达式接口,根据业务场景规范表达式
  2. type Expression interface {
  3.   Interpret(context Context) int
  4. }
复制代码
 
 
更多语言版本

不同语言实现设计模式,请关注:https://github.com/microwind/design-pattern

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册