浅谈Java解释器模式

作者:KnightHONG 时间:2021-08-23 23:45:59 

**请注意!请注意!!!**今天讲给大家讲解非常“有用”的设计模式,解释器模式!!!

设计模式有三大种类,一种是创建型模式,一种是结构型模式,最后一种是行为性模式,那么解释器模式属于哪一种呢?带领大家一起来了解学习解释器模式!

本次介绍围绕着以下五点展开。什么是解释器模式?用来做什么?怎么做?有哪些优点?有哪些不足?

解释器模式顾名思义,就是用来定义解释

给定一种特定语言,这个语言有特定的文法,解释器可以解释这个语言中的句子含义。即解释器提供一种语言,如java,同时它也提供一种手段去解析java语言写出来的代码。

大家可能也会想到这就是类似编译原理,一个算术表达式要经过词法分析,语法分析,构建语法树啥的;还有正则表达式;SQL解析,编译器等等,其实都是解析式模式的一种实现

那怎么做?一个是说要有像编译原理中的终结符非终结符,构建一颗语法树。同时需要有一个环境类,来管理输入和输出

这里我们举一个例子,输入一个表达式a+b-c+d-e,同时给这5个变量赋值,计算出它的值。那么使用解释器模式要如何实现?

我们为解释器定义一个抽象解释类Expression,所有的流转通过interpreter方法实现。

上下文管理输入输出使用一个HashMap去实现。

定义符号解释类SymbolExpression,加法解释类AddExpreesion,减法解释类SubExpression

类图:

浅谈Java解释器模式

具体代码实现:


public abstract class Expression {

// map中携带了表达式中的变量名(key) 和 对应的值(value)
   public abstract int interpreter(Map<String, Integer> var);

}

public class VarExpression extends Expression {

// 表达式中对应的变量名
   String key;

public VarExpression(String var) {
       this.key = var;
   }

@Override
   public int interpreter(Map<String, Integer> var) {
       return var.get(key);
   }
}

public class SymbolExpression extends Expression {

// +或-符号 左右两边的表达式
   Expression var1;
   Expression var2;

public SymbolExpression(Expression var1, Expression var2) {
       this.var1 = var1;
       this.var2 = var2;
   }

@Override
   public int interpreter(Map<String, Integer> var) {
       // 实现抽象方法
       // 该类不需要用到该方法 默认返回0
       return 0;
   }
}

public class AddExpression extends SymbolExpression {

public AddExpression(Expression var1, Expression var2) {
       super(var1, var2);
   }

@Override
   public int interpreter(Map<String, Integer> var) {
       return var1.interpreter(var) + var2.interpreter(var);
   }
}

public class SubExpression extends SymbolExpression {

public SubExpression(Expression var1, Expression var2) {
       super(var1, var2);
   }

@Override
   public int interpreter(Map<String, Integer> var) {
       return var1.interpreter(var) - var2.interpreter(var);
   }

}

public class Calculator {

// 表达式
   private Expression expression;

// 解析出表达式
   public Calculator(String expStr) {
       Stack<Expression> stack = new Stack<>();
       Expression left, right = null;
       char[] expStrCharArray = expStr.toCharArray();

for(int i = 0; i < expStrCharArray.length; i++) {
           switch (expStrCharArray[i]) {
               case '+':// 加法运算 获取左边表达式 右边数值
                   left = stack.pop();
                   right = new VarExpression(String.valueOf(expStrCharArray[++i]));
                   stack.push(new AddExpression(left, right));
                   break;
               case '-':// 减法运算 获取左边表达式 右边数值
                   left = stack.pop();
                   right = new VarExpression(String.valueOf(expStrCharArray[++i]));
                   stack.push(new SubExpression(left, right));
                   break;
               default:// 表达式中的变量
                   stack.push(new VarExpression(String.valueOf(expStrCharArray[i])));
                   break;
           }
       }
       // 最后会获得被Expression包装起来的一个表达式
       this.expression = stack.pop();
   }

// 计算结果
   public int run(Map<String, Integer> var) {
       return this.expression.interpreter(var);
   }
}

public class Client {

public static void main(String[] args) throws IOException {
       String expStr = getExpStr();
       Map<String, Integer> var = getValue(expStr);
       Calculator calculator = new Calculator(expStr);
       System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
   }

//获得表达式
   public static String getExpStr() {
       return "a+b-c+d-e";
   }

//获得值映射
   public static HashMap<String, Integer> getValue(String expStr) throws IOException {
       HashMap<String, Integer> map = new HashMap<>();

for(char ch : expStr.toCharArray()) {
           if(ch != '+' && ch != '-' ) {
               if(! map.containsKey(String.valueOf(ch))) {
                   System.out.print("请输入" + String.valueOf(ch) + "的值:");
                   String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                   map.put(String.valueOf(ch), Integer.valueOf(in));
               }
           }
       }

return map;
   }

}

结果

/*
请输入a的值:1
请输入b的值:3
请输入c的值:5
请输入d的值:7
请输入e的值:9
运算结果:a+b-c+d-e=-3
*/

或许看代码会有点云里雾里,希望大家能手动敲一遍,或许会对整个过程有更进一步的理解,在编码的同时不断思考,提升自我。

很容易发现解释器模式是属于行为性模式的一种,这种模式更关注对象之间的通信。

解释器模式优点,结构清晰,可拓展性好。但也有缺点,一般用在比较底层场景,平常敲代码可使用的场景比较少,并且解释器模式采用的是递归的方式,当语言比较长,性能不高;同时如果文法比较复杂,也需要更多的相应解释类。

来源:https://blog.csdn.net/KnightHONG/article/details/120693753

标签:Java,解释器,模式
0
投稿

猜你喜欢

  • 详解Java如何进行Base64的编码(Encode)与解码(Decode)

    2023-01-31 18:53:34
  • Java文件快速copy复制实例代码

    2021-05-27 12:25:22
  • 使用IDEA搭建SSM框架的详细教程(spring + springMVC +MyBatis)

    2023-04-24 07:35:45
  • jdk8使用stream实现两个list集合合并成一个(对象属性的合并)

    2023-08-05 16:49:30
  • Java操作pdf的工具类itext的处理方法

    2023-07-14 11:51:53
  • 详解Alibaba Java诊断工具Arthas查看Dubbo动态代理类

    2021-08-04 03:16:28
  • Java可变个数形参的方法实例代码

    2023-01-15 18:35:56
  • Java中获取文件大小的详解及实例代码

    2023-02-27 08:12:27
  • 详解Java单元测试之Junit框架使用教程

    2022-03-06 02:55:56
  • Java用数组实现循环队列的示例

    2022-06-26 15:09:48
  • Java 8 Function函数式接口及函数式接口实例

    2022-04-13 14:55:05
  • Mybatis通过数据库表自动生成实体类和xml映射文件

    2022-01-11 07:05:46
  • Mybatis中注解@MapKey的使用详解

    2023-11-24 21:43:35
  • 5种Android数据存储方式汇总

    2023-08-06 06:49:04
  • mybatisPlus返回Map类型的集合

    2022-01-31 13:37:07
  • 基于java 线程的几种状态(详解)

    2022-08-31 19:51:47
  • 浅析JDK12的五大重要新特性(推荐)

    2023-01-28 19:09:24
  • MyBatis自定义映射关系和关联查询实现方法详解

    2021-12-18 21:25:28
  • 微信开发--自定义菜单查询返码乱码的解决方法

    2023-11-25 04:47:55
  • Jsoup解析html实现招聘信息查询功能

    2022-01-08 19:38:07
  • asp之家 软件编程 m.aspxhome.com