设计模式之解释器模式
解释器模式:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
解释器模式需要解决的是,如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的例子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决问题。
用了解释器模式,就意味着可以很容易地改变和扩展语法,因为该模式使用类来表示文法规则,你可以使用继承来改变或扩展该文法。解释器的不足之处是,该模式为文法中的每条规则至少定义了一个类,因此包含许多规则的文法难以管理和维护,所以当文法非常复杂时,建议使用其他技术如语法分析程序或编译器生成器来处理。
一个简单的音乐解释器实现:
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{ String playKey = context.getText().substring(0, 1); context.setText(context.getText().substring(2)); double playValue = Double.parseDouble(context.getText().substring(0, context.getText().indexOf(" "))); context.setText(context.getText().substring(context.getText().indexOf(" ") + 1)); execute(playKey, playValue); } } public abstract void execute(String key, double value); }
public class Note extends Expression{ @Override public void execute(String key, double value) { // TODO Auto-generated method stub 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 + " "); } }
public class Scale extends Expression{ @Override public void execute(String key, double value) { // TODO Auto-generated method stub String scale = ""; int val = (int) value; switch(val){ case 1: scale = "低音"; break; case 2: scale = "中音"; break; case 3: scale = "高音"; break; } System.out.print(scale + " "); } }
public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub PlayContext context = new PlayContext(); System.out.println("上海滩: "); context.setText("O 2 E 0.5 G 0.5 A 3 E 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){ String str = context.getText().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); } }catch(Exception e){ e.printStackTrace(); } } }
这个例子不能代表解释器模式的全貌,因为它只有终结符表达式,而没有非终结符的表达式,要想真正理解解释器模式,还得研究其他例子。