动机(Motivate):
在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。
在这种情况下,将特定领域的问题表达为某种文法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。
意图(Intent):
给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
结构图(Struct):
生活中的例子:
适用性:
1.当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
而当存在以下情况时该模式效果最好:
2.该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达工,这样可以节省空间而且还可能节省时间。
3.效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种
形式。例如:正则表达式通常被转换成状态机。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍
是有用的。
代码实现:
客户端代码如下:
2 {
3 static void Main(string[] args)
4 {
5 string roman = "五千四百三十二"; //5432
6 Context context = new Context(roman);
7
8 //Build the 'parse tree'
9 ArrayList tree = new ArrayList();
10 tree.Add(new OneExpression());
11 tree.Add(new TenExpression());
12 tree.Add(new HundredExpression());
13 tree.Add(new ThousandExpression());
14
15 //Interpret
16 foreach (Expression exp in tree)
17 {
18 exp.Interpret(context);
19 }
20 Console.WriteLine("{0} = {1}", roman, context.Data);
21 //Wait for user
22 Console.Read();
23 }
24 }
创建一个抽象类Expression,来描述共同的操作。
2 {
3 protected Dictionary<string, int> table = new Dictionary<string, int>(9);
4 public Expression()
5 {
6 table.Add("一", 1);
7 table.Add("二", 2);
8 table.Add("三", 3);
9 table.Add("四", 4);
10 table.Add("五", 5);
11 table.Add("六", 6);
12 table.Add("七", 7);
13 table.Add("八", 8);
14 table.Add("九", 9);
15 }
16 public virtual void Interpret(Context context)
17 {
18 if(context.Statement.Length==0)
19 {
20 return;
21 }
22 foreach(string key in table.Keys)
23 {
24 int value=table[key];
25 if(context.Statement.EndsWith(key + GetPostifix()))
26 {
27 context.Data +=value*Multiplier();
28 context.Statement = context.Statement.Substring(0,context.Statement.Length- this.GetLength());
29 }
30
31 if(context.Statement.EndsWith("零"))
32 {
33 context.Statement = context.Statement.Substring(0, context.Statement.Length - 1);
34 }
35 if (context.Statement.Length == 0)
36 {
37 return;
38 }
39 }
40 }
41
42 public abstract string GetPostifix();
43 public abstract int Multiplier();
44 public virtual int GetLength()
45 {
46 return this.GetPostifix().Length + 1;
47 }
48 }
然后创建一个公共类Context,定义一些全局信息。
2 {
3 private string statement;
4 private int data;
5
6 //Constructor
7 public Context(string statement)
8 {
9 this.statement = statement;
10 }
11 //Properties
12 public string Statement
13 {
14 get { return statement; }
15 set { statement = value; }
16 }
17 public int Data
18 {
19 get { return data; }
20 set { data = value; }
21 }
22 }
2 {
3 public override string GetPostifix()
4 {
5 return "";
6 }
7 public override int Multiplier() { return 1; }
8 public override int GetLength()
9 {
10 return 1;
11 }
12 }
13 public class TenExpression : Expression
14 {
15 public override string GetPostifix()
16 {
17 return "十";
18 }
19 public override int Multiplier() { return 10; }
20 public override int GetLength()
21 {
22 return 2;
23 }
24 }
25 public class HundredExpression : Expression
26 {
27 public override string GetPostifix()
28 {
29 return "百";
30 }
31 public override int Multiplier() { return 100; }
32 public override int GetLength()
33 {
34 return 2;
35 }
36 }
37 public class ThousandExpression : Expression
38 {
39 public override string GetPostifix()
40 {
41 return "千";
42 }
43 public override int Multiplier() { return 1000; }
44 public override int GetLength()
45 {
46 return 2;
47 }
48 }
Interpreter实现要点:
Interpreter模式的应用场合是interpreter模式应用中的难点,只有满足"业务规则频繁变化,且类似的模式不断重复出现,并且容易抽象为语法规则的问题"才适合使用Interpreter模式。
使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便地“扩展”文法。
Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具。