给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
优点:
- 将每个语法规则表示成一个类,方便实现语言。
- 因为语法由许多类表示,可以轻易改变或拓展此语言。
- 通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如复杂的程序验证等。
缺点:
- 当语法规则的数目太大时,这个模式可能会变得非常复杂。
类图
- Context:包含解释器之外的一些全局信息,可以是正在解析的语言字符串输入流
- AbstractExpression:抽象表达式,声明一个抽象的解释操作
- Client:客户端代码,构建表示该文法定义的语言中一个特定句子的抽象语法树

实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public class Context {
private String input; private String output; public String getInput() { return input; } public void setInput(String input) { this.input = input; } public String getOutput() { return output; } public void setOutput(String output) { this.output = output; } }
|
1 2 3 4 5
| public abstract class AbstractExpression {
public abstract void interprete(Context context);
}
|
1 2 3 4 5 6 7 8
| public class TerminalExpression extends AbstractExpression {
@Override public void interprete(Context context) { System.out.println("终端解释器"); }
}
|
1 2 3 4 5 6 7 8
| public class NonTerminalExpression extends AbstractExpression {
@Override public void interprete(Context context) { System.out.println("非终端解释器"); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| import java.util.ArrayList; import java.util.List;
public class Client {
public static void main(String[] args) { Context context = new Context(); List<AbstractExpression> list = new ArrayList<AbstractExpression>(); list.add(new TerminalExpression()); list.add(new NonTerminalExpression()); list.add(new TerminalExpression()); for(AbstractExpression exp: list) { exp.interprete(context); } }
}
|
例:实现A&&B,A和B只能是布尔型:true和false
1 2 3 4 5
| public abstract class Expression {
public abstract boolean interpret(String info);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class TerminalExpression extends Expression {
@Override public boolean interpret(String info) { if (info.equals("true")) { return true; } else if (info.equals("false")) { return false; } else { throw new RuntimeException("不合法的表达式"); } }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class AndExpression extends Expression {
private Expression exp1; private Expression exp2;
public AndExpression(Expression exp1, Expression exp2) { this.exp1 = exp1; this.exp2 = exp2; }
@Override public boolean interpret(String info) { String[] strings = info.split("&&"); return exp1.interpret(strings[0]) && exp2.interpret(strings[1]); }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| public class Context {
private Expression expression;
public Context() { Expression exp1 = new TerminalExpression(); Expression exp2 = new TerminalExpression(); expression = new AndExpression(exp1, exp2); }
public boolean getResult(String info) { boolean res = expression.interpret(info); return res; }
}
|
1 2 3 4 5 6 7 8 9
| public class Client {
public static void main(String[] args) { Context context = new Context(); boolean res = context.getResult("true&&true"); System.out.println(res); } }
|