demo描述:做一个计算器(显仅限加法和减法),输入要计算的公式然后输入要计算的数字,通过解释器将输入的数字翻译成输入公式中对应的参数
demo代码:
抽象类表达式:
public abstract class Expression {
//公式的数据部分,用参数代替各个位置数字,将输入数字解释道对应的参数上,例:
//输入:a+b-c
//解释后得到:HashMap{a=10,b=20,c=40}
//返回内容为计算得到的结果,具体运算交个子类
public abstract int interpreter(HashMapvar);
}
变量解释器:
public class VarExpression extends Expression {
//key=a,b,c
private String key;
public VarExpression(String key) {
this.key = key;
}
//var是{a=10,b=20,c=40}
//根据变量名称返回对应的值
@Override
public int interpreter(HashMap var) {
return var.get(this.key);
}
}
抽象预算符号解释器:
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 var) {
return 0;
}
}
加、减法解释器;
public class AddExpression extends SymbolExpression {
public AddExpression(Expression left, Expression right) {
super(left, right);
}
//处理相加
//var仍是{a=10,b=20,c=40}
public int interpreter(HashMap var) {
return super.left.interpreter(var) + super.right.interpreter(var);
}
}
public class SubExpression extends SymbolExpression {
public SubExpression(Expression left, Expression right) {
super(left, right);
}
//处理相减
//var仍是{a=10,b=20,c=40}
public int interpreter(HashMap var) {
return super.left.interpreter(var) - super.right.interpreter(var);
}
}
解释执行部分:
public class Calculator {
//定义表达式
private Expression expression;
public Calculator(String expStr) {
//安排运算先后顺序
Stack 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 '+':
//从stack中取出left
left = stack.pop();
//取出right
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:
//var是变量就创建VarExpression对象并push到stack
stack.push(new VarExpression(String.valueOf(charArray[i])));
break;
}
}
//遍历完charArray后,stack就是最后的Expression
this.expression = stack.pop();
}
public int run(HashMap var) {
//将表达式a+b和var{a=10,b=20}绑定,然后进行解释执行
return this.expression.interpreter(var);
}
}
客户端:
public class Client {
public static void main(String[] args) throws IOException {
String expStr = getExpStr();//a+b+c
HashMap var = getValue(expStr);//var {a=10,b=20,c=40}
Calculator calculator = new Calculator(expStr);
System.out.println("运算结果:" + expStr + "=" + calculator.run(var));
}
//获得表达式
public static String getExpStr() throws IOException {
System.out.println("请输入表达式:");
return (new BufferedReader(new InputStreamReader(System.in))).readLine();
}
//获得值映射
public static HashMap getValue(String expStr) throws IOException {
HashMap map = new HashMap<>();
for (char ch : expStr.toCharArray()) {
if (ch != '+' && ch != '-') {
if (!map.containsKey(String.valueOf(ch))) {
System.out.println("请输入" + String.valueOf(ch) + "的值:");
String in =
(new BufferedReader(new InputStreamReader(System.in))).readLine();
map.put(String.valueOf(ch), Integer.valueOf(in));
}
}
}
return map;
}
}
demo类图:
类图分析:将解释器抽象未两种,一种是变量解释器,用来将将输入的数字与公式的变量对应上;另一种是运算符号的解释器,用来将运算符号左右的数字进行运算。1处可扩展运算符,在2处加上扩展的运算符的case分支,2处可以改成工厂,让扩展更优雅
适用场景:编译器、运算表达式、正则表达式等适用,做结果集映射时也可用,比如id与name的映射;
总结:解释器模式给定一个表达式,定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子,相当于做了一个转换。
它包含以下角色:
Context:环境角色,含有解释器之外的全局信息
AbstractExpression:抽象表达式,声明一个抽象的解释操作,这个方法为抽象语法树中所有节点所共享
TerminalExpression:中介符表达式,为文法中的中介符实现解释操作
NonTermialExpression:非中介符表达式,为文法中的非中介符实现解释操作