定义
建立一个解释器解释程序的逻辑与业务。也就是将一个比较复杂的业务分解成语法树或者是逻辑树。
类图
代码
1 /// <summary> 2 /// 抽象表达式 3 /// </summary> 4 public abstract class Expression 5 { 6 public abstract int Interprete(Dictionary<string, int> dicParameters); 7 } 8 /// <summary> 9 /// 变量表达式(变量) 10 /// </summary> 11 public class VarExpress : Expression 12 { 13 private string key; 14 public VarExpress(string key) 15 { 16 this.key = key; 17 } 18 public override int Interprete(Dictionary<string, int> dicParameters) 19 { 20 if (dicParameters.ContainsKey(key)) 21 { 22 return dicParameters[key]; 23 } 24 else 25 { 26 throw new Exception(string.Format("{0} is not avaliable", key)); 27 } 28 } 29 } 30 /// <summary> 31 /// 计算符号表达式 32 /// </summary> 33 public abstract class SymbolExpress : Expression 34 { 35 protected Expression leftExpression; 36 protected Expression rightExpression; 37 public SymbolExpress(Expression left, Expression right) 38 { 39 leftExpression = left; 40 rightExpression = right; 41 } 42 } 43 /// <summary> 44 /// 加法表达式 45 /// </summary> 46 public class AddExpress : SymbolExpress 47 { 48 public AddExpress(Expression left, Expression right) : base(left, right) 49 { 50 51 } 52 public override int Interprete(Dictionary<string, int> dicParameters) 53 { 54 return leftExpression.Interprete(dicParameters) + rightExpression.Interprete(dicParameters); 55 } 56 } 57 /// <summary> 58 /// 减法表达式 59 /// </summary> 60 public class SubExpress : SymbolExpress 61 { 62 public SubExpress(Expression left, Expression right) : base(left, right) 63 { 64 65 } 66 public override int Interprete(Dictionary<string, int> dicParameters) 67 { 68 return leftExpression.Interprete(dicParameters) - rightExpression.Interprete(dicParameters); 69 } 70 } 71 /// <summary> 72 /// 计算器 73 /// </summary> 74 public class Calculator 75 { 76 private Expression expression; //表达式 77 78 public Calculator(String expressionString) 79 { 80 Stack<Expression> stack = new Stack<Expression>(); 81 82 char[] charArray = expressionString.ToCharArray(); 83 84 Expression left = null; 85 86 Expression right = null; 87 88 for (int i = 0; i < charArray.Length; i++) 89 { 90 91 switch (charArray[i]) 92 { 93 94 case '+': //加法 95 96 //加法结果放到堆栈中 97 98 left = stack.Pop(); 99 100 right = new VarExpress((charArray[++i]).ToString()); 101 102 stack.Push(new AddExpress(left, right)); 103 104 break; 105 106 case '-': 107 108 left = stack.Pop(); 109 110 right = new VarExpress((charArray[++i]).ToString()); 111 112 stack.Push(new SubExpress(left, right)); 113 114 break; 115 //当然还有乘法/除法等 116 default: //默认就是变量 117 stack.Push(new VarExpress((charArray[i]).ToString())); 118 break; 119 120 } 121 122 } 123 this.expression = stack.Pop(); 124 125 } 126 127 /// <summary> 128 /// 计算 129 /// </summary> 130 /// <param name="parameters"></param> 131 /// <returns></returns> 132 public int Run(Dictionary<String, int> parameters) 133 { 134 return this.expression.Interprete(parameters); 135 136 } 137 138 }
调用部分
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 Calculator c = new Calculator("a+b-c"); 6 Dictionary<string, int> dic = new Dictionary<string, int>(); 7 dic.Add("a", 100); 8 dic.Add("b", 10); 9 dic.Add("c", 20); 10 int result = c.Run(dic); 11 Console.WriteLine(result.ToString()); 12 Console.ReadLine(); 13 } 14 }
总结
计算表达式就是一个非常经典的解释器模式的体现。当然像语法的解析、表达式的解析等引入解释器模式大大方便了实现与理解。像例子中的加减运算的实现,通过定义加减运算表达式和变量表达式,再通过栈的临时存储,很好的实现了通过解释给出的表达式,而实现计算的效果。当然当看到变量表达式是叶子节点,而运算表达式却相当于枝节点,怎么跟组合表达式有些类似呢?最终还是回到设计模式的关键点,还是他们关注点不一样,组合在于包含组成,他的组成方式可能是集合,而且它更多的体现的包含关系。而解释器在于解释,是一种行为。通过自身内部的迭代解释得出最终的运算,并得出结果。
其实,解释器用得还是比较少的,感觉蛮高大上的。