[设计模式/Java] 设计模式之解释器模式【27】

概述:解释器模式 := Interpreter Pattern ∈ 行为型模式

模式定义

  • 解释器模式Interpreter Pattern)提供了评估语言的语法表达式的方式

属于行为型模式

  • 解释器模式给定一个语言 ,定义它的文法的一种表示 ,并定义一个解释器 ,这个解释器 使用该表示来解释语言中的句子

  • 这种模式被用在 SQL 解析符号处理引擎等。

  • 模式的意图

定义一种语言的文法表示,并创建一个解释器,该解释器能够解释该语言中的句子。。

  • 主要解决的问题

解释器模式用于构建一个能够解释特定语言或文法句子的解释器

模式结构

解释器模式包含以下几个主要角色:

  • 抽象表达式(Abstract Expression):定义了解释器的抽象接口,声明了解释操作的方法,通常是一个抽象类或接口。
  • 终结符表达式(Terminal Expression):实现了抽象表达式接口的终结符表达式类,用于表示语言中的终结符(如变量、常量等),并实现了对应的解释操作。
  • 非终结符表达式(Non-terminal Expression):实现了抽象表达式接口的非终结符表达式类,用于表示语言中的非终结符(如句子、表达式等),并实现了对应的解释操作。
  • 上下文(Context) :包含解释器之外的一些全局 信息,在解释过程中提供给解释器使用,通常用于存储变量 的值、保存解释器的状态等。
  • 客户端(Client):创建并配置具体的解释器对象,并将需要解释的表达式传递给解释器进行解释。

适用场景

  • 当某一特定类型的问题频繁出现,并且可以通过一种简单的语言来表达这些问题的实例时。

实现方式

  • 定义【文法】:明确语言的终结符和非终结符。
  • 构建【语法树】:根据语言的句子构建对应的语法树结构。
  • 创建【环境类】:包含解释过程中所需的全局信息,通常是一个HashMap。

关键代码

  • 终结符与非终结符:定义语言的文法结构。
  • 环境类:存储解释过程中需要的外部环境信息。

模式特点

优点

  • 可扩展性好:容易添加新的解释表达式的方式。
  • 灵活性:可以根据需要轻松扩展或修改文法。
  • 易于实现简单文法:对于简单的语言,实现起来相对容易。

缺点

  1. 使用场景有限:只适用于适合使用解释的简单文法。
  2. 维护困难:对于复杂的文法,维护和扩展变得困难。
  3. 类膨胀:可能会产生很多类,每个文法规则对应一个类。
  4. 递归调用:解释器模式通常使用【递归调用】,这可能难以理解和跟踪。

使用建议

  • 在需要解释执行语言中的句子时,考虑使用解释器模式。
  • 确保文法简单,以避免系统变得过于复杂。
  • 解释器模式在 Java 中可能不是首选,如果遇到适用场景,可以考虑使用如expression4J之类的库来代替。

案例实践

案例总结

  • 编译器:解释器模式可以用于编译器设计,将源代码解释为目标代码。
  • 正则表达式:解释器模式可以用于解析和执行正则表达式。
  • SQL解析:解释器模式可以用于解析和执行SQL语句。
  • 文本模板渲染引擎 : 用于将各层级的环境信息渲染到文本模板中,生成最终的SQL、HTML等。著名的文本模板渲染引擎有:Jinjia(2) / Thymeleaf / Freemaker 等。

CASE 解释器模式的简单实现(性别/婚姻)

  • 我们将创建一个接口 Expression 和实现了 Expression 接口的实体类。
  • 定义作为上下文中主要解释器的 TerminalExpression 类。
  • 其他的类 OrExpression、AndExpression 用于创建组合式表达式
  • InterpreterPatternDemo,我们的演示类使用 Expression 类创建规则和演示表达式的解析。

表达式接口 : Expression

java 复制代码
public interface Expression {
   public boolean interpret(String context);
}

表达式接口的实现类: TerminalExpression / OrExpression / AndExpression

  • TerminalExpression
java 复制代码
public class TerminalExpression implements Expression {
   
   private String data;
 
   public TerminalExpression(String data){
      this.data = data; 
   }
 
   @Override
   public boolean interpret(String context) {
      if(context.contains(data)){
         return true;
      }
      return false;
   }
}
  • OrExpression
java 复制代码
public class OrExpression implements Expression {
   private Expression expr1 = null;
   private Expression expr2 = null;
 
   public OrExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }
 
   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) || expr2.interpret(context);
   }
}
  • AndExpression
java 复制代码
public class AndExpression implements Expression {
   private Expression expr1 = null;
   private Expression expr2 = null;
 
   public AndExpression(Expression expr1, Expression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }
 
   @Override
   public boolean interpret(String context) {      
      return expr1.interpret(context) && expr2.interpret(context);
   }
}

Client : InterpreterPatternDemo

  • InterpreterPatternDemo : 使用 Expression 类来创建规则,并解析它们。
java 复制代码
public class InterpreterPatternDemo {
   //规则:Robert 和 John 是男性
   public static Expression getMaleExpression(){
      Expression robert = new TerminalExpression("Robert");
      Expression john = new TerminalExpression("John");
      return new OrExpression(robert, john);    
   }
 
   //规则:Julie 是一个已婚的女性
   public static Expression getMarriedWomanExpression(){
      Expression julie = new TerminalExpression("Julie");
      Expression married = new TerminalExpression("Married");
      return new AndExpression(julie, married);    
   }
 
   public static void main(String[] args) {
      Expression isMale = getMaleExpression();
      Expression isMarriedWoman = getMarriedWomanExpression();
 
      System.out.println("John is male? " + isMale.interpret("John"));
      System.out.println("Julie is a married women? " 
      + isMarriedWoman.interpret("Married Julie"));
   }
}

out

log 复制代码
John is male? true
Julie is a married women? true

CASE 开源 SQL 解析引擎 - Apche Calcite

  • 推荐文献

CASE 开源语法分析工具 - Antlr

  • 推荐文献

Y 推荐文献

X 参考文献

相关推荐
TDengine (老段)25 分钟前
TDengine 时间函数 TODAY() 用户手册
大数据·数据库·物联网·oracle·时序数据库·tdengine·涛思数据
码界奇点34 分钟前
KingbaseES一体化架构与多层防护体系如何保障企业级数据库的持续稳定与弹性扩展
数据库·架构·可用性测试
悟乙己1 小时前
数据科学家如何更好地展示自己的能力
大数据·数据库·数据科学家
皆过客,揽星河1 小时前
mysql进阶语法(视图)
数据库·sql·mysql·mysql基础语法·mysql进阶语法·视图创建修改删除
tuokuac2 小时前
Redis 的相关文件作用
数据库·redis·缓存
鹧鸪云光伏与储能软件开发3 小时前
投资储能项目能赚多少钱?小程序帮你测算
运维·数据库·小程序·光伏·光伏设计软件·光伏设计
2301_779503764 小时前
MySQL主从同步--主从复制进阶
数据库·mysql
beijingliushao5 小时前
58-正则表达式
数据库·python·mysql·正则表达式
诗句藏于尽头5 小时前
DJANGO后端服务启动报错及解决
数据库·笔记·django
手握风云-5 小时前
MySQL数据库精研之旅第十五期:索引的 “潜规则”(下)
数据库