解释器模式:给定一个语言,定义它的文法的一种表示。并定义一个解释器,这个解释器使用该表示来解释
语言中的句子。
1.如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。
这样就可以构造一个解释器,该解释器通过解释这些句子来解决该问题。
2.当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
3.使用解释器模式时,可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,
可使用继承来改变或扩展该文法。 也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,
这些类都易于直接编写。
4.抽象语法树的每一个节点都代表一个语句,而在每个节点上都可以执行解释方法。这个解释方法的
执行就代表这个语句被解释。
5.一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。
6.不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。
建议当文法非常复杂时,使用其它的技术如语法分析程序或编译器生成器来处理。
/** * 抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中的所有节点所共享。 */ public abstract class AbstractExpression { public abstract void interpret(Context context); }
/** * 终结符表达式,实现与文法中的终结符相关联的解释操作。 * 文法中每一个终结符都有一个具体的终结表达式与之相对应。 */ public class TerminalExpression extends AbstractExpression{ @Override public void interpret(Context context) { System.out.println("终端解释器"); } }
/** * 非终结符表达式,为文法中的非终结符实现解释操作。 * 对文法中的每一条规则R1,R2...Rn都需要一个具体的非终结符表达式类。 * 解释操作以递归方式调用上面所提到的代表R1,R2....Rn中的各个符号的实例变量。 */ public class NonTerminalExpression extends AbstractExpression{ @Override public void interpret(Context context) { System.out.println("非终端解释器"); } }
/** * 包含解释器之外的一些全局信息。 */ public class Context { private String intput; private String output; public String getIntput() { return intput; } public void setIntput(String intput) { this.intput = intput; } public String getOutput() { return output; } public void setOutput(String output) { this.output = output; } }
扫描二维码关注公众号,回复:
816869 查看本文章
public class Main { 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()); list.add(new TerminalExpression()); for(AbstractExpression expression:list){ expression.interpret(context); } } }
解释器模式示例:音乐解释器事例(音符,音阶,音速等)
/** * 演奏内容类 */ public class PlayContext { // 演奏文本 private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } }
/** * 表达式类 */ public abstract class Expression { //解释器 public void interpret(PlayContext context){ if(context.getText().length()==0){ return; }else{ // 获取playKey和playValue //(例:"O 3 E 0.5 G 0.5 A 3 "playKey为O,playValue为3) char playKey = context.getText().substring(0,1).charAt(0); context.setText(context.getText().substring(2)); Double playValue = Double.parseDouble(context.getText() .substring(0,context.getText().indexOf(" "))); // 获得playKey和playValue后,将其从演奏文本中移除 // (例:"O 3 E 0.5 G 0.5 A 3 "变成"E 0.5 G 0.5 A 3 ") context.setText(context.getText().substring(context.getText().indexOf(" ")+1)); execute(playKey, playValue); } } // 执行,抽象方法执行不同的文法子类,有不同的执行处理。 public abstract void execute(char key,Double value); }
/** * 音符类,终结符表达式 */ public class Note extends Expression{ @Override public void execute(char key, Double value) { String note = ""; // 如果获得的key是C则演奏1(do),D则演奏2(Re) 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+" "); } }
/** * 音阶类,终结符表达式 */ public class Scale extends Expression{ @Override public void execute(char key, Double value) { String scale = ""; // 如果获得的key是O并且value是1则演奏低音,2则是中音,3则是高音 switch(value.intValue()){ case 1: scale = "低音"; break; case 2: scale = "中音"; break; case 3: scale = "高音"; break; } System.out.print(scale+" "); } }
/** * 音速类,终结符表达式 */ public class Speed extends Expression{ @Override public void execute(char key, Double value) { // T 1000 表示每节拍一秒,T 500 表示每节拍半秒 String speed = ""; if(value<500){ speed = "快速"; }else if(value>=1000){ speed = "慢速"; }else{ speed = "中速"; } System.out.print(speed+" "); } }
public class Main { public static void main(String[] args) { PlayContext context = new PlayContext(); System.out.println("上海滩:"); context.setText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3"); Expression expression = null; try{ while (context.getText().length()>0){ char str = context.getText().substring(0,1).charAt(0); switch (str){ case 'O': // 当首字母是O时,表达式实例化为音阶 expression = new Scale(); break; case 'T': // 当首字母是T时,表达式实例化为音速 expression = new Speed(); break; case 'C': case 'D': case 'E': case 'F': case 'G': case 'A': case 'B': case 'P': // 当首字母是CDEFGAB以及休止符P时,表达式实例化为音符 expression = new Note(); break; } expression.interpret(context); } }catch(Exception e){ e.printStackTrace(); } } }
输出结果如下:
上海滩: 中速 中音 3 5 6 3 5 5 2 3 5 6 高音 1 中音 6 5 1 3