> 文档中心 > 二十一、解释器模式——解析表达式和脚本

二十一、解释器模式——解析表达式和脚本

文章目录

  • 解释器模式
    • 1.Expression
    • 2.Caculator
    • 3.Main
  • 总结

设计模式是面向问题、场景而总结产生的设计思路。是解决问题的套路。23 种经典的设计模式。它们又可以分为三大类:创建型、结构型、行为型。

行为型 包含了 观察者模式、模板模式、策略模式、职责链模式、状态模式、迭代器模式、 访问者模式、备忘录模式、命令模式、解释器模式、中介模式 总共11种模式。

解释器模式

给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语句中的表达式

  • 抽象表达式角色(Expression):声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称作解释操作。
  • 终结符表达式角色(Terminal Expression):实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。
  • 非终结表达式角色(Nonterminal Expression):文法中的每一条规则都需要一个具体的非终结符表达式。比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式
  • 环境角色(Context):这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,很多情况下我们使用Map来充当环境角色就够了。

1.Expression

定义表达式,有2中子类,一类是变量型,从map中就可以取值了。一类是符号型,这里支持加减。

public abstract class Expression {    public abstract int interpreter(HashMap<String,Integer> var);}public class SymbolExpression extends Expression{    protected Expression left;    protected Expression right;    public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right;    }    @Override    public int interpreter(HashMap<String, Integer> var) { return 0;    }}public class AddExpression extends SymbolExpression{    public AddExpression(Expression left, Expression right) { super(left, right);    }    @Override    public int interpreter(HashMap<String, Integer> map) { return super.left.interpreter(map) + super.right.interpreter(map);    }}public class MinusExpression extends SymbolExpression{    public MinusExpression(Expression left, Expression right) { super(left, right);    }    @Override    public int interpreter(HashMap<String, Integer> map) { return super.left.interpreter(map) - super.right.interpreter(map);    }}

2.Caculator

Caculator 将字符串解析为表达式。其方法是将字符组合成一个复杂的表达式对象,每个对象的left和right都是表达式。

public class Calculator {    public Expression parse(String expStr) { // expStr = a+b Stack<Expression> stack = new Stack<>(); char[] charArray = expStr.toCharArray();// [a, +, b] Expression left = null; Expression right = null; //针对不同的情况,做处理 for (int i = 0; i < charArray.length; i++) {     switch (charArray[i]) {  case '+': //      left = stack.pop();      right = new VarExpression(String.valueOf(charArray[++i]));      stack.push(new AddExpression(left, right));      break;  case '-': //      left = stack.pop();      right = new VarExpression(String.valueOf(charArray[++i]));      stack.push(new MinusExpression(left, right));      break;  default:      stack.push(new VarExpression(String.valueOf(charArray[i])));      break;     } } return stack.pop();    }}

3.Main

public class Main {    public static void main(String[] args) throws IOException { String expStr = new BufferedReader(new InputStreamReader(System.in)).readLine(); HashMap<String,Integer> map = new HashMap<>(); for(char c:expStr.toCharArray()) {     if(c!='+'&&c!='-'&&!map.containsKey(String.valueOf(c))){  String val = new BufferedReader(new InputStreamReader(System.in)).readLine();  map.put(String.valueOf(c),Integer.valueOf(val));     } } Calculator calculator = new Calculator(); Expression expression = calculator.parse(expStr); System.out.println("运算结果:" + expStr + "=" + expression.interpreter(map));    }}

运行结果:

a+b+c1235运算结果:a+b+c=20

总结

解释器模式代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分成一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。

设计模式系列在github上有一个开源项目,主要是本系列博客的demo代码。https://github.com/forestnlp/designpattern
如果您对软件开发、机器学习、深度学习有兴趣请关注本博客,将持续推出Java、软件架构、深度学习相关专栏。
您的支持是对我最大的鼓励。

二十一、解释器模式——解析表达式和脚本 《新程序员》:云原生和全面数字化实践 二十一、解释器模式——解析表达式和脚本 50位技术专家共同创作,文字、视频、音频交互阅读