设计模式(二十三)解释器模式

解释器模式(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 }

 

posted @ 2015-06-21 23:21  壬子木  阅读(113)  评论(0)    收藏  举报