解释器模式
定义:解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。
解释器模式的结构
下面就以一个示意性的系统为例,讨论解释器模式的结构。系统的结构图如下所示:
模式所涉及的角色如下所示:
(1)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称做解释操作。
(2)终结符表达式(Terminal Expression)角色:实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
(3)非终结符表达式(Nonterminal Expression)角色:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+”就是非终结符,解析“+”的解释器就是一个非终结符表达式。
(4)环境(Context)角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。
具体案例
//上下文环境角色
public class Context {
private Map<Variable,Integer> valueMap = new HashMap<Variable,Integer>();
public void addValue(Variable x , int y)
{
valueMap.put(x , y);
}
public int LookupValue(Variable x)
{
int i = valueMap.get(x);
return i ;
}
}
//抽象表达式角色,也可以用接口来实现
public abstract class Expression {
public abstract int interpret(Context con);
}
//终结符表达式角色
public class Constant extends Expression {
private int i;
public Constant(int i){
this.i = i;
}
public int interpret(Context con){
return i;
}
}
public class Variable extends Expression{
public int interpret(Context con)
{
// this为调用interpret方法的Variable对象
return con.LookupValue(this);
}
}
//非终结符表达式角色
public class Add extends Expression {
private Expression left, right;
public Add(Expression left, Expression right)
{
this.left = left;
this.right = right;
}
public int interpret(Context con)
{
return left.interpret(con) + right.interpret(con);
}
}
public class Subtract extends Expression {
private Expression left, right;
public Subtract(Expression left, Expression right)
{
this.left = left;
this.right = right;
}
public int interpret(Context con)
{
return left.interpret(con) - right.interpret(con);
}
}
public class Multiply extends Expression {
private Expression left, right;
public Multiply(Expression left, Expression right)
{
this.left = left;
this.right = right;
}
public int interpret(Context con)
{
return left.interpret(con) * right.interpret(con);
}
}
public class Division extends Expression{
private Expression left, right;
public Division(Expression left, Expression right)
{
this.left = left;
this.right = right;
}
public int interpret(Context con)
{
try {
return left.interpret(con) / right.interpret(con);
} catch (ArithmeticException ae)
{
System.out.println("被除数为0!");
return -11111;
}
}
}
//测试程序,计算 (a*b)/(a-b+2)
public class Test {
private static Expression ex,exa,exs,exm;
private static Context con;
public static void main(String[] args)
{
con = new Context();
// 设置变量、常量
Variable a = new Variable();
Variable b = new Variable();
Constant c = new Constant(2);
// 为变量赋值
con.addValue(a, 10);
con.addValue(b, 8);
// 运算,对句子的结构由我们自己来分析,构造
exs=new Subtract(a, b);
exa=new Add(exs, c);
exm=new Multiply(a, b);
ex = new Division(exm, exa);
System.out.println("运算结果为:" + ex.interpret(con));
}
}
优缺点
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。
但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊!
以上内容来自平时所看书籍和网络资源整理测试所得,如有不完善之处,欢迎指正!