解释器模式
定义一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
类结构图
Context
包含解释之外的一些全局信息。
AbstractExpression
声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。
TerminalExpression
终结符表达式,实现与文法中的终结符相关联的解释操作。
NonterminalExpression
非终结符表达式,为文法中的非终结符实现解释操作。
代码示例
乐谱大家都见过,那么我们来自定义一下 O 表示音阶、C D E F G A B 表示 Do-Re-Mi-Fa-So-La-Ti。
public class Context {
private String playText;
public String getPlayText() {
return playText;
}
public void setPlayText(String playText) {
this.playText = playText;
}
}
public abstract class Expression {
abstract void excute(String key, String value);
public void interpret(Context context) {
if (null == context.getPlayText() || "".equals(context.getPlayText())) {
return;
}
// 解析的字符串例如 O 3 E 0.5
String playKey = context.getPlayText().substring(0, 1);
context.setPlayText(context.getPlayText().substring(2));
String value = context.getPlayText().substring(0, context.getPlayText().indexOf(" "));
context.setPlayText(context.getPlayText().substring(context.getPlayText().indexOf(" ") + 1));
excute(playKey, value);
}
}
public class Note extends Expression {
@Override
void excute(String key, String value) {
String note = "";
switch (key) {
case "C":
note = "1";
break;
case "D":
note = "2";
break;
case "E":
note = "3";
break;
case "F":
note = "4";
break;
case "G":
note = "5";
break;
case "A":
note = "6";
break;
case "B":
note = "7";
break;
}
System.out.print(note + "\t");
}
}
public class Scale extends Expression {
@Override
void excute(String key, String value) {
String scale = "";
switch (Integer.parseInt(value)) {
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
}
System.out.print(scale + "\t");
}
}
客户端示例
public class ExpressionClient {
public static void main(String[] args) {
Context context = new Context();
context.setPlayText(
"O 2 E null G null A 3 E null G null D 3 E null G null A null O 3 C 1 O 2 A null G 1 C null E null E 3 ");
Expression expression = null;
while (context.getPlayText().length() > 0) {
String str = context.getPlayText().substring(0, 1);
switch (str) {
case "O":
expression = new Scale();
break;
case "C":
case "D":
case "E":
case "F":
case "G":
case "A":
case "B":
case "P":
expression = new Note();
break;
}
expression.interpret(context);
}
}
}
运行结果
中音 3 5 6 3 5 2 3 5 6 高音 1 中音 6 5 1 3 3
Process finished with exit code 0
优点
可以比较方便的修改和扩展语法规则。
缺点
几乎针对每一个规则都定义了一个类,所以如果一个语法的规则比较多,那对于语法的维护工作也会变得非常困难。