解释器模式
解释器模式(Interpreter Pattern):是指给定一门语言,定义它的文法的一种表示(如:加减乘除表达式和正则表达式等),然后再定义一个解释器,该解释器用来解释我们的文法表示(表达式)。
解释器模式是一种按照规定的语法来进行解析的一种设计模式,属于行为型模式。
终结符表达式和非终结符表达式
终结符表达式(Terminal Expression):实现文法中与终结符有关的解释操作。文法中每一个终结符都有一个具体的终结符表达式与之相对应。比如我们的 R=M+N 运算,M 和 N 就是终结符,对应的解析 M 和 N 的解释器就是终结符表达式。
非终符结表达式(Nonterminal Expression):实现文法中与非终结符有关的解释操作。文法中的每一条规则都对应了一个非终结符表达式。非终结表达式一般是文法中的运算符或者关键字,如上面公示:R=M+N 中的“+”号就是非终结符,解析“+”号的解释器就是一个非终结符表达式。
示例:我们通过简单的加减法表达式进行举例说明...
package cn.liangyy.interpreter;
/**
* 顶层的表达式接口
*/
public interface IExpression {
/**
* 用来解释表达式的方法
* @return
*/
int interpret();
}
复制代码
package cn.liangyy.interpreter;
/**
* 非终结表达式-抽象表达式
*/
public abstract class AbstractNonTerminalExpression implements IExpression {
//非终结表达式左边表达式,一般为数字
protected IExpression leftExpression;
//非终结表达式右边表达式,一般为数字
protected IExpression rightExpression;
public AbstractNonTerminalExpression(IExpression leftExpression, IExpression rightExpression) {
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
}
复制代码
package cn.liangyy.interpreter;
/**
* 非终结表达式-具体表达式-加法表达式
*/
public class AddExpression extends AbstractNonTerminalExpression {
public AddExpression(IExpression leftExpression, IExpression rightExpression) {
super(leftExpression, rightExpression);
}
/**
* 用来解释表达式的方法
* @return
*/
@Override
public int interpret() {
//解释器,将左右两个终结符的值相加
return this.leftExpression.interpret() + this.rightExpression.interpret();
}
}
复制代码
package cn.liangyy.interpreter;
/**
* 非终结表达式-具体表达式-减法表达式
*/
public class SubExpression extends AbstractNonTerminalExpression {
public SubExpression(IExpression leftExpression, IExpression rightExpression) {
super(leftExpression, rightExpression);
}
/**
* 用来解释表达式的方法
* @return
*/
@Override
public int interpret() {
//解释器,将左右两个终结符的值相减
return this.leftExpression.interpret() - this.rightExpression.interpret();
}
}
复制代码
package cn.liangyy.interpreter;
/**
* 终结表达式-数值表达式
*/
public class NumberExpression implements IExpression {
//终结表达式的值
private int value;
public NumberExpression(String value) {
this.value = Integer.valueOf(value);
}
/**
* 用来解释表达式的方法
* @return
*/
@Override
public int interpret() {
//解释非终结表达式
return this.value;
}
}
复制代码
package cn.liangyy.interpreter;
import java.util.Stack;
/**
* 上下文信息类
*/
public class ExpressionContext {
//定义一个栈,计算一般都用栈,利用其先进后出的特性
private Stack<IExpression> stack = new Stack<>();
public ExpressionContext(Stack<IExpression> stack) {
this.stack = stack;
}
private void parse(String expression){
//为了简单,直接以空格来切割,所以测试的时候每个数字和符号之间都要有空格
String[] elementArr = expression.split(" ");
for (int i = 0;i < elementArr.length;i++){
String element= elementArr[i];
if (element.equals("+")){ //加法
//站内元素出栈
IExpression leftExpression = stack.pop();
//取出+号后的下一个元素
IExpression rightExpression = new NumberExpression(elementArr[++i]);
//计算
IExpression addExpression = new AddExpression(leftExpression,rightExpression);
//将计算结果压入栈
stack.push(new NumberExpression(addExpression.interpret()+""));
}else if (element.equals("-")){ //减法
//栈内元素出栈
IExpression leftExpression = stack.pop();
//取出-号后的下一个元素
IExpression rightExpression = new NumberExpression(elementArr[++i]);
//计算
IExpression subExpression = new SubExpression(leftExpression,rightExpression);
//将计算结果压入栈
stack.push(new NumberExpression(subExpression.interpret()+""));
}else{
//如果是数字则直接入栈
stack.push(new NumberExpression(element));
}
}
}
/**
* 运算结果
* @return
*/
public int calcuate(){
//经过前面解析,到这里stack内只会剩下唯一一个数字,即运算结果
return stack.pop().interpret();
}
}
复制代码
package cn.liangyy.interpreter;
/**
* 解释器模式-测试
*/
public class TestInterpreter {
public static void main(String[] args) {
//注意每个符号之间要包含空格
ExpressionContext context = new ExpressionContext("123 + 345 + 678 - 234");
System.out.println(context.calcuate());
context = new ExpressionContext("123 - 345 + 890");
System.out.println(context.calcuate());
}
}
复制代码
上述例子就是通过简单的加减法实现的一个解释器模式,这样我们对解释器模式的设计思想就有了一个很清楚的认识学习。
解释器模式适用场景
解释器模式优点扩展性比较强。从我们上面的示例中可以看出来了,每一个表达式都是一个类,所以如果需要修改某一个规则只需要修改对应的表达式类就可以了,扩展的时候也只需要新增一个新类就可以了。
解释器模式缺点
评论