• 设计模式(23)解释器模式


    一、介绍:

    1、定义:解释器(Interpreter)模式是一种对象的行为模式。给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

    2、组成结构:


    (1)AbstractExpression(抽象表达式):约定解释器的解释操作,主要是一个interpret()方法。这个接口作为抽象语法树中所有节点(即终结符表达式和非终结符表达式)所共享

    1. public abstract class AbstractExpression {
    2. public abstract void interpret(Context context);
    3. }

    (2) TerminalExpression(终结符表达式):用来实现文法中和终结符相关的解释操作,不再包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的叶子对象,可以有多种终结符解释器。

    1. public class TerminalExpression extends AbstractExpression{
    2. @Override
    3. public void interpret(Context context) {
    4. System.out.println("终结符解释器");
    5. }
    6. }

    (3)NonterminalExpression(非终结表达式):用来实现文法中和非终结符相关的解释操作,通常一个解释器对应一个语法规则,可以包含其它的解释器,如果用组合模式来构建抽象语法树的话,就相当于组合模式中的组合对象,可以有多种非终结符解释器。公式R=R1+R2中,R1、R2为终结符表达式,+为非终结表达式(其后需要跟随一个终结符表达式)。

    1. public class NonterminalExpression extends AbstractExpression{
    2. @Override
    3. public void interpret(Context context) {
    4. System.out.println("非终结符解释器");
    5. }
    6. }

    (4) Context类(包含解释器之外的一些全局信息):也称“上下文”,常用HashMap来代替,通常包含解释器之外的一些全局信息(解释器需要的数据,或是公共的功能)。

    1. public class Context {
    2. private String input;
    3. private String output;
    4. //GetSet方法省略
    5. }

    客户端,构建文法表示的抽象语法树(Abstract Syntax Tree),该抽象语法树由终结符表达式和非终结符表达式的实例装配而成),并调用解释操作interpret()方法。 

    1. Context context = new Context();
    2. List list = new ArrayList();
    3. list.add(new TerminalExpression());
    4. list.add(new NonterminalExpression());
    5. list.add(new TerminalExpression());
    6. list.add(new NonterminalExpression());
    7. for (AbstractExpression abstractExpression : list) {
    8. abstractExpression.interpret(context);
    9. }

    3、适用场景:解释器模式似乎使用面不是很广,它描述了一个语言解释器是如何构成的,在实际应用中,我们可能很少去构造一个语言的文法。建议在以下情况中选用解释器模式: 当有一个语言需要解释执行,并且可以将语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式。  

    二、demo:

    1、加减法计算器:

    1. //抽象表达式
    2. public interface AbstractExpression {
    3. int interprete(HashMap var);
    4. }
    5. //终结符表达式
    6. public class VarExpression implements AbstractExpression {
    7. private String key;
    8. public VarExpression(String key) {
    9. this.key = key;
    10. }
    11. public int interprete(HashMap var) {
    12. return (Integer) var.get(this.key);
    13. }
    14. }
    15. //加法符号 非终结表达式
    16. public class AddExpression implements AbstractExpression{
    17. private AbstractExpression left;
    18. private AbstractExpression right;
    19. public AddExpression(AbstractExpression left, AbstractExpression right) {
    20. this.left = left;
    21. this.right = right;
    22. }
    23. // 把左右两个表达式运算的结果加起来
    24. public int interprete(HashMap var) {
    25. return this.left.interprete(var) + this.right.interprete(var);
    26. }
    27. }
    28. //减法符号 非终结表达式
    29. public class SubExpression implements AbstractExpression{
    30. private AbstractExpression left;
    31. private AbstractExpression right;
    32. public SubExpression(AbstractExpression left, AbstractExpression right) {
    33. this.left = left;
    34. this.right = right;
    35. }
    36. // 把左右两个表达式运算的结果加起来
    37. public int interprete(HashMap var) {
    38. return this.left.interprete(var) - this.right.interprete(var);
    39. }
    40. }
    1. //封装计算器类
    2. public class Calculator {
    3. private AbstractExpression expression;
    4. public Calculator(String expStr) {
    5. // 定义一个堆栈,安排运算的先后顺序
    6. Stack<AbstractExpression> stack = new Stack<AbstractExpression>();
    7. // 表达式拆分为字符数组
    8. char[] charArray = expStr.toCharArray();
    9. // 运算
    10. AbstractExpression left = null;
    11. AbstractExpression right = null;
    12. for (int i = 0; i < charArray.length; i++) {
    13. switch (charArray[i]) {
    14. case '+':
    15. left = stack.pop();
    16. right = new VarExpression(String.valueOf(charArray[++i]));
    17. stack.push(new AddExpression(left, right));
    18. break;
    19. case '-':
    20. left = stack.pop();
    21. right = new VarExpression(String.valueOf(charArray[++i]));
    22. stack.push(new SubExpression(left, right));
    23. break;
    24. default: // 公式中的变量
    25. stack.push(new VarExpression(String.valueOf(charArray[i])));
    26. }
    27. }
    28. // 把运算结果抛出来
    29. this.expression = stack.pop();
    30. }
    31. // 计算结果
    32. public int calculate(HashMap<String, Integer> var) {
    33. return this.expression.interprete(var);
    34. }
    35. }
    36. //客户端
    37. public static void main(String args[]){
    38. // 构造运算元素的值列表
    39. HashMap<String, Integer> ctx = new HashMap<String, Integer>();
    40. ctx.put("a", 10);
    41. ctx.put("b", 20);
    42. ctx.put("c", 30);
    43. ctx.put("d", 40);
    44. ctx.put("e", 50);
    45. ctx.put("f", 60);
    46. Calculator calc = new Calculator("a+b-c");
    47. int result = calc.calculate(ctx);
    48. System.out.println("Result of a+b-c: " + result);
    49. calc = new Calculator("d-a-b+c");
    50. result = calc.calculate(ctx);
    51. System.out.println("Result of d-a-b+c: " + result);
    52. }
    53. 输出:
    54. Result of a+b-c: 0
    55. Result of d-a-b+c: 40

  • 相关阅读:
    129. 求根节点到叶节点数字之和
    5年在职经验之谈:2年功能测试、3年自动化测试,从入门到不可自拔...
    acwing算法基础之搜索与图论--最短路问题
    9月7日作业
    基于hadoop的智能软考刷题系统
    store redux在项目中的应用
    Feign远程调用丢失请求头
    Linux--进程替换
    【docker】docker搭建nginx的ssl模块
    Java实现LeetCode题目
  • 原文地址:https://blog.csdn.net/w_t_y_y/article/details/134155863