参考:https://blog.youkuaiyun.com/weixin_48052161/article/details/119716593
这是我们23个设计模式中最后一个设计模式了,大家或许也没想到吧,竟然是编译原理上的编译器,这样说可能不对,因为编译器分为几个部分组成呢,比如词法分析器、语法分析器、语义分析器、中间代码优化器以及最终的最终代码生成器。而这个解释器其实就是完成了对语法的解析,将一个个的词组解释成了一个个语法范畴,之后拿来使用而已。
为什么会有这个解释器模式呢,我想这是从编译原理中受到启发的,使用了这样的一个解释器可以在Java语言之上在定义一层语言,这种语言通过Java编写的解释器可以放到Java环境中去执行,这样如果用户的需求发生变化,比如打算做其他事情的时候,只用在自己定义的新的语言上进行修改,对于Java编写的代码不需要进行任何的修改就能在Java环境中运行,这是非常有用的。这就好像,虽然不管怎么编译,最终由中间代码生成最终代码(机器码)是依赖于相应的机器的。但是编译器却能理解高级语言和低级语言,无论高级语言的程序是怎么样编写的,编译器的代码是不用修改的,而解释器模式就是想做一个建立在Java和我们自定义语言之间的编译器。
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
解释器模式(Interpreter Pattern)是指给定一门语言,定义它的文法的一种表示(如:加减乘除表达式和正则表达式等),然后再定义一个解释器,该解释器用来解释我们的文法表示(表达式)。
解释器模式是一种按照规定的语法(文法)来进行解析的一种设计模式,属于行为型模式
解释器模式:相当于自己设计一种语言处理算法;
代码演示:
案例 1 :计算器
需求:
模拟简单的加减法表达式
抽象表达式角色接口类: IExpression
package com.example.dtest.design23.interpreter;
public interface IExpression {
int interpret();
}
继承接口类的抽象的非终结表达式: AbstractNonTerminalExpression
package com.example.dtest.design23.interpreter;
/**
* 非终结表达式-抽象表达式
*/
public abstract class AbstractNonTerminalExpression implements IExpression{
//protected类型,因为子类要继承
protected IExpression leftExpression;
protected IExpression rightExpression;
public AbstractNonTerminalExpression(IExpression leftExpression,IExpression rightExpression){
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
}
继承接口的终结表达式角色类: NumberExpression
package com.example.dtest.design23.interpreter;
public class NumberExpression implements IExpression{
private int value;
public NumberExpression(String value){
this.value = Integer.valueOf(value);
}
@Override
public int interpret() {
return this.value;
}
}
具体非终结表达式角色类,继承抽象类: AddExpression , SubExpression
本次示例中只列举加法和减法,所以我们还需要一个加法类和一个减法类:
AddExpression 加法类
package com.example.dtest.design23.interpreter;
public class AddExpression extends AbstractNonTerminalExpression{
public AddExpression(IExpression leftExpression,IExpression rightExpression){
super(leftExpression,rightExpression);
}
@Override
public int interpret() {
return this.leftExpression.interpret() + this.rightExpression.interpret();
}
}
SubExpression 减法类
package com.example.dtest.design23.interpreter;
public class SubExpression extends AbstractNonTerminalExpression{
public SubExpression(IExpression leftExpression,IExpression rightExpression){
super(leftExpression,rightExpression);
}
@Override
public int interpret() {
return this.leftExpression.interpret() - this.rightExpression.interpret();
}
}
上下文环境角色门面类:ExpressionContext
package com.example.dtest.design23.interpreter;
import java.util.Stack;
public class ExpressionContext {
private Integer currValue;//记录当前运算结果,空表示暂未运算
private Stack<IExpression> stack = new Stack<>();
public ExpressionContext(String expression){
this.parse(expression);
}
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));//如果是数字则直接入栈
}
}
}
public int calcuate(){
return stack.pop().interpret();//经过前面解析,到这里stack内只会剩下唯一一个数字,即运算结果
}
}
测试类:
package com.example.dtest.design23.interpreter;
public class TestInterpreter {
public static void main(String[] args) {
ExpressionContext context = new ExpressionContext("1 + 1 - 1");
System.out.println(context.calcuate());
context = new ExpressionContext("10 - 20 + 10");
System.out.println(context.calcuate());
}
}