解释器模式可以用来为语言创建解释器,也就是说可以再创造出一门语言。
场景描述
为了说明解释器模式的实现方式,给出一个最简单的文法和对应的解释器模式的实现,就是模拟Java语言中对布尔表达式进行操作和求值。比如说,给定一个表达式:(true AND x) OR (y AND (NOT x))
,求该表达式的值是true
还是false
。这个语言简单的文法如下:
|
|
文法中涉及到的名词,在代码实现部分均会有对应的类,下面就来看一下如何实现。
代码实现
Expression抽象,Context类是整个运行环境的上下文,该类稍候给出。
123456789101112131415161718192021222324public abstract class Expression {/*** 解释给定的任意表达式*/public abstract boolean interpret(Context ctx);/*** 检验两个表达式在结构上是否相同*/public abstract boolean equals(Object o);/*** 返回表达式的HashCode*/public abstract int hashCode();/*** 将表达式转换成字符串*/public abstract String toString();}Variable类用于创建一个有名字的变量,比如
new Variable("x")
,所以该类给出了一个成员变量name
12345678910111213141516171819202122232425262728293031323334353637383940414243public class Variable extends Expression {private String name;public Variable(String name) {this.name = name;}/*** 解释操作* 从Context中找出变量对应的value值*/public boolean interpret(Context ctx) {return ctx.lookup(this);}/*** 检验两个表达式在结构上是否相同*/public boolean equals(Object o) {if (o instanceof Variable) {return this.name.equals(((Variable) o).name);}return false;}/*** 返回表达式的HashCode*/public int hashCode() {return (this.toString()).hashCode();}/*** 将表达式转换成字符串*/public String toString() {return name;}}实现Context类,该类用于保存上下文,其实就是运行环境中所有变量对应的布尔值
123456789101112131415161718192021public class Context {private HashMap map = new HashMap();/*** 给变量赋值*/public void assign(Variable var, boolean value) {map.put(var, value);}/*** 查找变量的值*/public boolean lookup(Variable var) {Boolean value = (Boolean) map.get(var);if (value == null) {throw new IllegalArgumentException();}return value;}}实现Constant类,因为是常量,所以该类的解释方法直接返回成员变量
value
的值123456789101112131415161718192021222324252627282930public class Constant extends Expression {private boolean value;public Constant(boolean value) {this.value = value;}public boolean interpret(Context ctx) {return value;}public boolean equals(Object o) {if (o instanceof Constant) {return this.value == ((Constant) o).value;}return false;}public int hashCode() {return (this.toString()).hashCode();}public String toString() {return Boolean.toString(value);}}实现And操作,作用是由两个布尔表达式通过逻辑与操作给出一个新的布尔表达式。
12345678910111213141516171819202122232425262728293031323334public class And extends Expression {private Expression left, right;public And(Expression left, Expression right) {this.left = left;this.right = right;}/*** 左表达式和右表达式分别解释操作之后再作&&操作*/public boolean interpret(Context ctx) {return left.interpret(ctx) && right.interpret(ctx);}public boolean equals(Object o) {if (o instanceof And) {return this.left.equals(((And) o).left) && this.right.equals(((And) o).right);}return false;}public int hashCode() {return (this.toString()).hashCode();}public String toString() {return "(" + left.toString() + " AND " + right.toString() + ")";}}实现Or操作,作用是由两个布尔表达式通过逻辑或操作给出一个新的布尔表达式。
12345678910111213141516171819202122232425262728293031public class Or extends Expression {private Expression left, right;public Or(Expression left, Expression right) {this.left = left;this.right = right;}public boolean interpret(Context ctx) {return left.interpret(ctx) || right.interpret(ctx);}public boolean equals(Object o) {if (o instanceof Or) {return this.left.equals(((Or) o).left) && this.right.equals(((Or) o).right);}return false;}public int hashCode() {return (this.toString()).hashCode();}public String toString() {return "(" + left.toString() + " OR " + right.toString() + ")";}}实现Not操作,作用是由一个布尔表达式通过逻辑非操作给出一个新的布尔表达式。
123456789101112131415161718192021222324252627282930public class Not extends Expression {private Expression exp;public Not(Expression exp) {this.exp = exp;}public boolean interpret(Context ctx) {return !exp.interpret(ctx);}public boolean equals(Object o) {if (o instanceof Not) {return this.exp.equals(((Not) o).exp);}return false;}public int hashCode() {return this.toString().hashCode();}public String toString() {return "(Not " + exp.toString() + ")";}}测试
1234567891011121314151617181920212223public class Test {public static void main(String[] args) {// 声明ContextContext ctx = new Context();// 声明x、y两个变量,并且存储到Context上下文中Variable x = new Variable("x");Variable y = new Variable("y");ctx.assign(x, false);ctx.assign(y, true);// 声明一个常量Constant c = new Constant(true);// 声明测试表达式:(true AND x) OR (y AND (NOT x))Expression exp = new Or(new And(c, x), new And(y, new Not(x)));// 解释声明的x、y变量并输出System.out.println("x = " + x.interpret(ctx));System.out.println("y = " + y.interpret(ctx));// 解释表达式并输出System.out.println(exp.toString() + " = " + exp.interpret(ctx));}}
个人感觉这个模式特别的地方是,Context中存储了表达式中用到的所有变量,并且头从到尾传递该对象;另外一点特别的是interpret方法的调用有点递归的意思。本章节就学到这里了。