解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用来解释语言中的句子。
一、解释器模式
解释器模式用来做各种各样的解释器,如正则表达式的解释器等等,其UML图如下所示:
解释器模式由以下部分组成:
抽象表达式(Expression):声明一个所有的具体表达式角色都要实现的抽象接口。该接口中的interpret()方法,称作解释操作。
终结符表达式(TerminalExpression):实现抽象表达式角色所要求的接口,文法中的每一个终结符都有一个具体终结表达式与之对应。比如R=R1+R2,R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
非终结符表达式(NonterminalExpression):文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字。比如R=R1+R2,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。
环境(Context):这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,给R1赋值1,R2赋值2,这些信息需要存放到环境中。
二、案列分析
我们用一个能够解释加减乘除四则运算的案列,学习解释器模式。
抽象表达式:
interface Expression{
int interpret(Context context);
}
终结符表达式:常量和变量
// 常量--终结符表达式
class Constant implements Expression{
private int i;
public Constant(int i) {
this.i = i;
}
@Override
public int interpret(Context context) {
return i;
}
}
// 变量--终结符表达式
class Variable implements Expression{
@Override
public int interpret(Context context) {
return context.lookValue(this);
}
}
非终结符表达式:加减乘除
class Add implements Expression{
private Expression left;
private Expression right;
public Add(Expression left,Expression right) {
this.left = left;
this.right= right;
}
@Override
public int interpret(Context context) {
return left.interpret(context)+right.interpret(context);
}
}
class Sub implements Expression{
private Expression left;
private Expression right;
public Sub(Expression left,Expression right) {
this.left = left;
this.right= right;
}
@Override
public int interpret(Context context) {
return left.interpret(context)-right.interpret(context);
}
}
class Mul implements Expression{
private Expression left;
private Expression right;
public Mul(Expression left,Expression right) {
this.left = left;
this.right= right;
}
@Override
public int interpret(Context context) {
return left.interpret(context) * right.interpret(context);
}
}
class Div implements Expression{
private Expression left;
private Expression right;
public Div(Expression left,Expression right) {
this.left = left;
this.right= right;
}
@Override
public int interpret(Context context) {
return left.interpret(context)/right.interpret(context);
}
}
环境:
class Context{
private Map valueMap=new HashMap<>();
public void addValue(Variable x,int y){
valueMap.put(x,y);
}
public int lookValue(Variable x){
return (int)valueMap.get(x);
}
}
客户端调用:
public class Test {
public static void main(String[] args) {
Context context = new Context();
Variable a = new Variable();
Variable b = new Variable();
Constant c= new Constant(100);
context.addValue(a,100);
context.addValue(b,20);
Expression e = new Div(new Mul(a,b),new Add(new Sub(a,b),c));
System.out.println("result="+e.interpret(context));
}
}
运行结果(代码亲测,可以通过):
代码地址:Interpreter
三、模式结语
解释器模式的优点:
易于改变和扩展文法。
每一条文法规则都可以表示为一个类,因此可以方便地实现一个简单的语言。
解释器模式的应用场景:
当一个语言需要解释执行,并可以将该语言中的句子表示为一个抽象语法树的时候,可以考虑使用解释器模式(如XML文档解释、正则表达式等领域)。
一些重复出现的问题可以用一种简单的语言来进行表达。
一个语言的文法较为简单.当执行效率不是关键和主要关心的问题时可考虑解释器模式。
欢迎大家评论留言,点击查看更多设计模式。