描述
- 对于形式变化比较多的情况下,可以把变化定义成节点,定义一个解释器,去逐步解析节点的合法性,得到最终结果。
- 比如计算器:1+2+3+4-5,1+2+3-4+5,…
- 把数字和+ - 定义成节点,由解释器去解析(提取语句规则,抽象成一种语言,然后解析这种语言的含义),得到最终结果。
定义语法规则:
- express:表达式( | :表示或的意思)
- plus:加法表达式
- minus:减法表达式
- value:最终结果
express ::= value | plus | minus
plus ::= express + express
minus ::= express - express
value ::= integer
角色
- 抽象表达式角色:定义解释器的接口,约定规范,提供解析方法:interpret。
- 终结符表达式角色:抽象表达式子类,用来实现终结符相关操作。如语法规则中的value。
- 非终结符表达式角色:抽象表达式子类,用来实现非终结符相关操作。如语法规则中的:plus等。
- 环境角色:定义解释器需要的数据,公共功能,传递所有解释器共享的数据。
- 客户端:将表达式装换为解释器对象解析的抽象语法树,让解释器解析获得结果。
实现
public class Test {
public static void main(String[] args) {
Environment environment = new Environment();
ParameterExpress a = new ParameterExpress("A");
ParameterExpress b = new ParameterExpress("B");
ParameterExpress c = new ParameterExpress("C");
ParameterExpress d = new ParameterExpress("D");
environment.add(a, 11);
environment.add(b, 2);
environment.add(c, 4);
environment.add(d, 6);
AbstractExpress express = new PlusExpress(new SubtractionExpress(new PlusExpress(a, b), c), d);
Integer interpret = express.interpret(environment);
System.out.println(express);
System.out.println(interpret);
}
}
abstract class AbstractExpress {
abstract Integer interpret(Environment environment);
}
class Environment {
private Map<ParameterExpress, Integer> parameterExpressIntegerMap = new HashMap<>();
public void add(ParameterExpress parameterExpress, Integer value) {
parameterExpressIntegerMap.put(parameterExpress, value);
}
public Integer get(ParameterExpress parameterExpress) {
return parameterExpressIntegerMap.get(parameterExpress);
}
}
class ParameterExpress extends AbstractExpress {
private String name;
ParameterExpress(String name){ this.name = name;}
@Override
Integer interpret(Environment environment) {
return environment.get(this);
}
@Override
public String toString() {
return name;
}
}
class PlusExpress extends AbstractExpress {
private AbstractExpress left;
private AbstractExpress right;
PlusExpress(AbstractExpress left, AbstractExpress right) {
this.left = left;
this.right = right;
}
@Override
Integer interpret(Environment environment) {
return left.interpret(environment) + right.interpret(environment);
}
@Override
public String toString() {
return left + "+" + right;
}
}
class SubtractionExpress extends AbstractExpress {
private AbstractExpress left;
private AbstractExpress right;
SubtractionExpress(AbstractExpress left, AbstractExpress right) {
this.left = left;
this.right = right;
}
@Override
Integer interpret(Environment environment) {
return left.interpret(environment) - right.interpret(environment);
}
@Override
public String toString() {
return left + "-" + right;
}
}
优点
- 易于扩展和改变表达式规则,表达式规则编写较为符合思考逻辑。符合开闭原则。
缺点
- 复杂文法难以维护,每种规则都需要一个类,类个数太多难以管理维护,递归,执行效率较低,调试较麻烦。
使用场景
- 当语言的文法较为简单,且执行效率不是问题,简单语法规则重复出现时。