解释器模式
定义
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器可以使用该表示来解释这个句子。
结构
Context:环境类,它包含除解释器以外的全局信息。
AbstractExpression:抽象解释器类,定义一个实现类的接口。
TerminalExpression:终结符表达式类,实现与文法中的终结符相关联的解释操作。
NonTerminalExpression:非终结符表达式类。
类图
抽象表达式类:
public abstract class AbstractExpression {
public abstract void interpreter(Context context);
}
环境类:
public class Context {
private String input;
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
}
终结符表达式:
public class TerminalExpression extends AbstractExpression {
@Override
public void interpreter(Context context) {
System.out.println("终端解释器");
}
}
非终结符表达式类:
public class NonTerminalExpression extends AbstractExpression {
@Override
public void interpreter(Context context) {
System.out.println("非终端解释器");
}
}
测试类:
public static void main(String[] args) {
Context context = new Context();
ArrayList<AbstractExpression> list = new ArrayList<AbstractExpression>();
list.add(new TerminalExpression());
list.add(new TerminalExpression());
list.add(new NonTerminalExpression());
list.add(new TerminalExpression());
for (AbstractExpression expression : list) {
expression.interpreter(context);
}
}
测试结果:
案例
我们都知道音乐是有乐谱的,根据乐谱可以演奏出动人的声音,那么乐谱是无法演奏的,必须通过音乐解释器将每个音符化成声音,乐谱分为音阶、音符、音速。本案例中音阶分为1、2、3档分别对应中高低音。音符分为C、D、E、F、G、A、B分别对应Do-Re-Mi-Fa-So-La-Ti。音速分为1、2、3档分别对应高中低速。
抽象表达式类:
public abstract class Expression {
public void play(PlayContext context){
/*
* 通过输入一串乐谱 O 2 E 0.5 C 1 D 0.5 T 1 F 1 O 3
* O 2 => 中音
* E 0.5 => Mi 0.5拍
* C 1 => Do 1拍
* D 0.5 => Re 0.5拍
* T 1 => 低速
* F 1 => Fa 1拍
* O 3 => 高音
*/
String text = context.getText();
String key = text.substring(0, 1);
text = text.substring(2);
String value = "";
if(text.indexOf(" ") > 0){
value = text.substring(0,text.indexOf(" "));
context.setText(text.substring(text.indexOf(" ")+1));
}else{
value = text.substring(0);
context.setText("");
}
execute(key,value);
}
public abstract void execute(String key,String value);
}
环境类:
public class PlayContext {
private String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
音符类:
public class Note extends Expression {
@Override
public void execute(String key, String value) {
String note = "";
switch (key) {
case "C": note = "Do"; break;
case "D": note = "Re"; break;
case "E": note = "Mi"; break;
case "F": note = "Fa"; break;
case "G": note = "So"; break;
case "A": note = "La"; break;
case "B": note = "Ti"; break;
}
System.out.print(note);
}
}
音阶类:
public class Step extends Expression{
@Override
public void execute(String key, String value) {
String step = "";
switch (value) {
case "1": step = "低音"; break;
case "2": step = "中音"; break;
case "3": step = "高音"; break;
}
System.out.print(step);
}
}
音速类:
public class Speed extends Expression{
@Override
public void execute(String key, String value) {
String speed = "";
switch (value) {
case "1": speed = "低速"; break;
case "2": speed = "中速"; break;
case "3": speed = "高速"; break;
}
System.out.print(speed);
}
}
测试类:
public static void main(String[] args) {
PlayContext context = new PlayContext();
context.setText("O 2 E 0.5 C 1 D 0.5 T 1 F 1 O 3");
Expression expression = null;
while(context.getText().length() > 0){
String tmp = context.getText().substring(0,1);
switch (tmp) {
case "O": expression = new Step(); break;
case "T": expression = new Speed(); break;
default: expression = new Note(); break;
}
expression.play(context);
}
}
测试结果:
优点
可扩展性好,灵活方便,符合开闭原则,符合依赖倒转原则。
缺点
使用场景较少,并且解释器类使用递归调用。