当前位置:网站首页>解释器模式
解释器模式
2022-07-29 20:37:00 【贺兰猪】
解释器模式平时用得不多,注意理解就行。所以直接偷懒搬运了, ~~~~~~~
1. 介绍
解释器模式(Interpreter Pattern)是一种行为型模式。给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
简单理解:例如给定一个表达式 a+b,然后设置 a 为1,b 为2,计算 a + b 的值。可以定义一个值解释器,它用来解释变量 a 和变量 b 的值,定义一个加法解释器,它用来解释 a + b ,即先通过值表达式解释变量 a 和变量 b 的值,然后将它们相加。
优点:
扩展性强。如果增加了新的语法,只需要增加对应的解释器。
可以轻松的解释简单语法。
缺点:
不适用于复杂的文法。对于复杂的文法,文法的类层次将变得庞大且无法管理。这时,使用语法分析程序生成器这样的工具比较好。
不常使用。解释器模式的适用场景比较少,是不常用的模式之一。
注意:
解释器模式是所有设计模式中比较难理解的模式之一。
2. 例子
实现一个计算器,当你输入例如 a + b + c 这样的加减法表达式并指定每个参数的值,计算这个表达式的结果。定义数值解析器用来解析变量(根据变量名来获取其值),定义加法解释器来解释加法(利用数值解析器解析两个变量的值,将它们的数值相加),定义减法解释器来解释减法(和加法解释器类似)。
类图:
Expression抽象类
代表的是表达式。
package interpreterPattern;
import java.util.HashMap;
/**
* 表达式类,是一个抽象类
* @author jxd
* @since 2021-06-12
*/
public abstract class Expression {
//解析公式和数值,key是公式中的参数,value是具体的数值
public abstract int interpreter(HashMap<String, Integer> var);
}VarExpression类
变量解释器,可以将变量解析为其对应的值,继承了Expression类。
package interpreterPattern;
import java.util.HashMap;
/**
* 变量解释器,根据变量名获取变量的值
* @author jxd
* @since 2021-06-12
*/
public class VarExpression extends Expression {
/**
* 变量名,在 变量名-值 的键值对中就是键
*/
private String key;
public VarExpression(String key) {
this.key = key;
}
/**
* 解释变量
*/
@Override
public int interpreter(HashMap<String, Integer> var) {
return var.get(this.key);
}
}SymbolExpression类
符号解释器类,继承了Expression类。
package interpreterPattern;
import java.util.HashMap;
/**
* 符号解释器类,是所有运算(+ - * /)解释器的父类
* 符号解析只与符号的左表达式和右表达式有关
* @author jxd
* @since 2021-06-12
*/
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;
}
}SubExpression类
减法表达式类,继承自 SymbolExpression 符号解释器。
package interpreterPattern;
import java.util.HashMap;
/**
* 减法解释器,继承自符号解释器,覆盖了父类中的interpreter(解释)方法
* @author jxd
* @since 2021-06-12
*/
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
/**
* 减法解释器中的解释方法
*/
public int interpreter(HashMap<String, Integer> var) {
// 例如:a - b == a-> 1 b->2 == 1 - 2 == -1
return super.left.interpreter(var) - super.right.interpreter(var);
}
}AddExpression类
加法解释器类,和减法解释器类及其类似。
package interpreterPattern;
import java.util.HashMap;
/**
* 加法解释器类
* @author jxd
* @since 2021-06-12
*/
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
/**
* 重写了interpreter方法
*/
public int interpreter(HashMap<String, Integer> var) {
return super.left.interpreter(var) + super.right.interpreter(var);
}
}Calculator类
代表的是计算器,利用解释器来计算表达式的结果。
package interpreterPattern;
import java.util.HashMap;
import java.util.Stack;
/**
* 计算器类
* @author jxd
* @since 2021-06-12
*/
public class Calculator {
//定义表达式
private Expression expression;
//构造函数传参,并解析
public Calculator(String expStr) {
//安排运算先后顺序
Stack<Expression> stack = new Stack<>();
//表达式拆分为字符数组
char[] charArray = expStr.toCharArray();
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 SubExpression(left, right));
break;
default: //公式中的变量
stack.push(new VarExpression(String.valueOf(charArray[i])));
break;
}
}
//栈中最后只会有一个表达式对象
this.expression = stack.pop();
}
//计算表达式
public int run(HashMap<String, Integer> var) {
return this.expression.interpreter(var);
}
}Client类
获取用户输入的表达式和表达式对应的值,利用计算机类来计算结果,并将结果友好的打印出来。
package interpreterPattern;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
/**
* 客户端,接收用户输入的表达式和变量的值,然后利用计算器来运算表达式的结果
* @author jxd
* @since 2021-06-12
*/
public class Client {
public static void main(String[] args) throws IOException {
String expStr = getExpStr();
HashMap<String, Integer> var = getValue(expStr);
Calculator calculator = new Calculator(expStr);
System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
}
/**
* 获得表达式
* @return 用户输入的表达式
* @throws IOException
*/
public static String getExpStr() throws IOException {
System.out.print("请输入表达式:");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}
/**
* 获得值映射
* @param expStr
* @return 每一个变量对应的值,是一个Map
* @throws IOException
*/
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;
}
}运行结果:

3. 总结
解释器模式就是为不同的语法设置不同的解释器,让后利用解释器来计算表达式的值或解释表达式的含义,关键在于如何实现解释器。
边栏推荐
- :class数组写法
- Fully automated machine learning modeling!The effect hangs the primary alchemist!
- VSCode配置终端为系统命令行
- Looking for a job - a chat with my cousin
- Permutations of a small feat: cantor
- 微博账号奇葩逻辑产品设计
- 单壁碳纳米管-DNA复合物(SWCNT-DNA)|作用机理
- First thoughts on the first attempt to avoid killing without a file (Part 1)
- 点击返回顶部
- QT安装、创建项目与调试,在VS中的使用:手把手教程
猜你喜欢

一 JS中Promise用法、二闭包的概念与用法、三对象创建的四种方式与区区别、四 如何声明一个类

.NET 6.0中使用Identity框架实现JWT身份认证与授权

940. Different subsequences II

RedisJson 横空出世!

微信小程序 31 分包机制

conda virtual environment | install and list problems

WeChat Mini Program 30 Customizing Templates and Obtaining User Login Credentials

1. Promise usage in JS, 2. The concept and usage of closures, 3. The difference between the four methods and areas of object creation, 4. How to declare a class

太卷了,企业级的智慧物业系统,也完全开源....

Analysis of Crypto in Pi 2
随机推荐
LeetCode 0144. 二叉树的前序遍历:二叉树必会题
PyQt5学习一(环境搭建)
【Nacos】nacos1.x 单机、内置数据库模式修改密码
【无标题】
一 JS中Promise用法、二闭包的概念与用法、三对象创建的四种方式与区区别、四 如何声明一个类
Break the rules!MongoDB introduces SQL?
The younger brother asked: Is the work of a programmer a day’s work of code?
The difference between uri and url is simple to understand (what is the difference between uri and url)
MySQL数据查询 - 简单查询
全景教程丨VR全景拍摄如何拍摄日出和日落的场景?
The sword refers to Offer II 097. Number of subsequences
336. Palindromic Pairs
解析掌握现代化少儿编程实操能力
LeetCode--single linked list--146.LRU cache
Unity determines whether a string can be converted to float type
LeetCode 593 有效的正方形[数学] HERODING的LeetCode之路
The demand for VR live broadcast marketing is increasing, and the data module is paving the way for us
ES6用法,面试大全
PEG-PEI共聚物/DNA复合物|甘草次酸修饰的长循环阳离子脂质体DNA复合物|解析说明
【数据库】mysql日期格式转换