设计模式(二十三)解释器模式
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语句中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
应用场景:当有一个语言需要解释执行,并且你可将该语言中的一个句子表示为一个抽象语法树时,可使用解释器模式。如:正则表达式、浏览器等应用。
优点:解释器模式可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法,也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。
不足:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译生成器来处理。

基本代码
1 // 抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享 2 abstract class AbstractExpression 3 { 4 public abstract void Interpret(Context context); 5 } 6 7 // 终结符表达式,实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口, 8 // 主要是一个 Interpret() 方法。文法中每一个终结符都有一个具体终结表达式与之相对应。 9 class TerminalExpression : AbstractExpression 10 { 11 public override void Interpret(Context context) 12 { 13 Console.WriteLine("终端解释器"); 14 } 15 } 16 17 // 非终结符表达式,为文法中的非终结符实现解释操作。对文法中的每一条规则R1、R2...Rn 都需要一个具体的非终结符表达式类。 18 // 通过实现抽象表达式的 Interpret() 方法实现解释器操作。解释操作以递归方式调用上面所提到的代表 R1、R2...Rn 中各个符号的实例变量 19 class NonterminalExpression : AbstractExpression 20 { 21 public override void Interpret(Context context) 22 { 23 Console.WriteLine("非终端解释器"); 24 } 25 } 26 27 // Context 包含解释器之外的一些全局信息 28 class Context 29 { 30 private string input; 31 public string Input 32 { 33 get { return input; } 34 set { input = value; } 35 } 36 37 private string output; 38 public string Output 39 { 40 get { return output; } 41 set { output = value; } 42 } 43 } 44 45 // 客户端构建表示该文法定义的语言中一个特定的句子的抽象语法树。 46 // 调用解释操作 47 static void Main(string[] args) 48 { 49 Context context = new Context(); 50 51 IList<AbstractExpression> list = new List<AbstractExpression>(); 52 list.Add(new TerminalExpression()); 53 list.Add(new NonterminalExpression()); 54 list.Add(new TerminalExpression()); 55 list.Add(new TerminalExpression()); 56 57 foreach(AbstractExpression exp in list) 58 { 59 exp.Interpret(context); 60 } 61 62 Console.Read(); 63 }
【例】

基本代码
1 // 演奏内容 2 class PlayContext 3 { 4 // 演奏文本 5 private string text; 6 public string PlayText 7 { 8 get { return text; } 9 set { text = value; } 10 } 11 } 12 13 // 抽象表达式 14 abstract class Expression 15 { 16 // 解释器 17 public void Interpret(PlayContext context); 18 { 19 if(context.PlayText.Length == 0) return; 20 else 21 { 22 string playKey = context.PlayText.Substring(0, 1); 23 context.PlayText = context.PlayText.Substring(2); 24 double playValue = Convert.ToDouble(context.PlayText.Substring(0, context.PlayText.IndexOf(" "))); 25 context.PlayText = context.PlayText.Substring(context.PlayText.IndexOf(" ") + 1); 26 27 Excute(playKey, playValue); 28 } 29 } 30 31 // 执行,不同的文法子类,有不同的执行处理 32 public abstract void Excute(string key, double value); 33 } 34 35 // 音符类 36 class Note : Expression 37 { 38 public override void Excute(string key, double value) 39 { 40 string note = ""; 41 switch(key) 42 { 43 case "C": 44 note = "1"; 45 break; 46 case "D": 47 note = "2"; 48 break; 49 case "E": 50 note = "3"; 51 break; 52 case "F": 53 note = "4"; 54 break; 55 case "G": 56 note = "5"; 57 break; 58 case "A": 59 note = "6"; 60 break; 61 case "B": 62 note = "7"; 63 break; 64 } 65 Console.WriteLine("{0}", note); 66 } 67 } 68 69 // 音符类 70 class Scale : Expression 71 { 72 public override void Excute(string key, double value) 73 { 74 string scale = ""; 75 switch(Convert.ToInt32(value)) 76 { 77 case 1: 78 scale = "低音"; 79 break; 80 case 2: 81 scale = "中音"; 82 break; 83 case 3: 84 scale = "高音"; 85 break; 86 } 87 Console.WriteLine("{0}", scale); 88 } 89 } 90 91 // 客户端 92 static void Main(string[] args) 93 { 94 PlayContext context = new PlayContext(); 95 Console.WriteLine("上海滩:"); 96 context.Playtext = "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 G 1 C 0.5 E 0.5 D 3"; 97 Expression expression = null; 98 try 99 { 100 while(context.PlayText.Length > 0) 101 { 102 string str = context.PlayText.Substring(0, 1); 103 switch(str) 104 { 105 case "O": 106 expression = new Scale(); 107 break; 108 case "C": 109 case "D": 110 case "E": 111 case "F": 112 case "G": 113 case "A": 114 case "B": 115 case "P": 116 expression = new Note(); 117 break; 118 } 119 expression.Interpret(context); 120 } 121 } 122 catch(Exception ex) 123 { 124 Console.WriteLine(ex.Message); 125 } 126 Console.Read(); 127 }

浙公网安备 33010602011771号