一、概述
在软件开发特别是DSL开发中常常需要使用一些相对较复杂的业务语言,如果业务语言使用频率足够高,且使用普通的编程模式来实现会导致非常复杂的变化,那么就可以考虑使用解释器模式构建一个解释器对复杂的业务语言进行翻译。这种做法虽然效率相对较低,但可以允许用户使用自定义的业务语言来处理逻辑,因此在效率不是关键问题的场合还是较为有用的。
二、解释器模式
解释器模式描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。其结构图如下:
AbstractExpression声明一个为抽象语法树中所有节点所共享的解释接口。
TerminalExpression表示终结符表达式,实现文法中终结符相关联的所有解释操作。
NonterminalExpression表示非终结符表达式,实现文法中所有非终结符的解释操作。
Context包含解释器外的一些全局信息。
Client构建语法树并调用解释器。
三、示例
我们我们就以中英文翻译系统为例来介绍解释器模式。
中英文对照字典如下。
1 public static class ChineseEnglishDict 2 { 3 private static Dictionary<string, string> _dictory = new Dictionary<string, string>(); 4 5 static ChineseEnglishDict() 6 { 7 _dictory.Add("this", "这"); 8 _dictory.Add("is", "是"); 9 _dictory.Add("an", "一个"); 10 _dictory.Add("apple", "苹果"); 11 } 12 13 public static string GetEnglish(string value) 14 { 15 return _dictory[value]; 16 } 17 }
首先定义AbstractExpression接口。
1 public interface IExpression 2 { 3 void Interpret(StringBuilder sb); 4 }
接着定义具体的Expression,这里包括对英文单词的翻译和对英文句号的翻译。
1 public class WordExpression : IExpression 2 { 3 private string _value; 4 5 public WordExpression(string value) 6 { 7 _value = value; 8 } 9 10 public void Interpret(StringBuilder sb) 11 { 12 sb.Append(ChineseEnglishDict.GetEnglish(_value.ToLower())); 13 } 14 } 15 16 public class SymbolExpression : IExpression 17 { 18 private string _value; 19 20 public SymbolExpression(string value) 21 { 22 _value = value; 23 } 24 25 public void Interpret(StringBuilder sb) 26 { 27 switch (_value) 28 { 29 case "." : 30 sb.Append("。"); 31 break; 32 } 33 } 34 }
最后将各部分解释器组合起来进行包装,方便用户调用。
1 public static class Translator 2 { 3 public static string Translate(string sentense) 4 { 5 StringBuilder sb = new StringBuilder(); 6 List<IExpression> expressions = new List<IExpression>(); 7 string [] elements = sentense.Split(new char [] {'.'}, StringSplitOptions.RemoveEmptyEntries); 8 foreach (string element in elements) 9 { 10 string[] words = element.Split(new char [] {' '}, StringSplitOptions.RemoveEmptyEntries); 11 foreach (string word in words) 12 { 13 expressions.Add(new WordExpression(word)); 14 } 15 expressions.Add(new SymbolExpression(".")); 16 } 17 foreach (IExpression expression in expressions) 18 { 19 expression.Interpret(sb); 20 } 21 return sb.ToString(); 22 } 23 }
让我们来看一下如何调用解释器。
1 static void Main(string[] args) 2 { 3 string englist = "This is an apple."; 4 string chinese = Translator.Translate(englist); 5 Console.WriteLine(chinese); 6 }