解释器模式(Interpreter Pattern) 任何可以承载信息的载体,都可以称之为语言,语言如果想被理解,需要按照特定的语法去编排生成,解释器就是根据语法规则去解释语言。
结构图:
角色:
抽象表达式(Abstract Expression):声明解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
终结符表达式(Terminal Expression):实现与语法中的元素相关联的解释操作,大多数情况下一个解释器模式中只有一个终结表达式,但有多个实例,对应不同的终结符。
非终结符表达式(Nonterminal Expression):语法中的每条规则对应于一个非终结表达式,非终结符表达式根据逻辑的复杂程度而增加,原则上每个语法规则都对应一个非终结符表达式
环境类(Context):用于存储解释器之外的一些全局信息,通常它临时存储了需要解释的语句。
适用场景:
日志、监控等分析场景下。
优点:
方便和扩展表示语言的语法,
每个语法规则对应一个类,符合单一原则。
缺点:
代码复杂度过高,继承过于复杂。
复杂表达式执行效率低。
代码(C#) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 public interface IAbstractExpression { bool Interpret (string info ) ; }public class TerminalExpression : IAbstractExpression { private List<string > ls = new List<string >(); public TerminalExpression (string [] data ) { for (var i = 0 ; i < data.Length; i++) { ls.Add(data[i]); } } public bool Interpret (string info ) { if (ls.Contains(info)) { return true ; } return false ; } }class NonterminalExpression : IAbstractExpression { private IAbstractExpression _cat; private IAbstractExpression _dog; public NonterminalExpression (IAbstractExpression cat, IAbstractExpression dog ) { _cat = cat; _dog = dog; } public bool Interpret (string str ) { return _cat.Interpret(str) || _dog.Interpret(str); } }public class MyContext { private string [] _cat = { "银渐层" , "英短" }; private string [] _dog = { "金毛" , "哈士奇" }; private IAbstractExpression _animal; public MyContext () { IAbstractExpression cat = new TerminalExpression(_cat); IAbstractExpression dog = new TerminalExpression(_dog); _animal = new NonterminalExpression(cat, dog); } public void FreeRide (string info ) { bool ok = _animal.Interpret(info); if (ok) { Console.WriteLine($"{info} ,是宠物" ); } else { Console.WriteLine($"{info} ,不是宠物" ); } } }var myContext = new MyContext(); myContext.FreeRide("金毛" );
最后 解释器模式的代码实现比较灵活,没有固定的模板。代码实现的核心思想,就是将语法解析的工作拆分到各个小类中,以此来避免大而全的解析类。一般的做法是,将语法规则拆分一些小的独立的单元,然后对每个单元进行解析,最终合并为对整个语法规则的解析。