一、问题产生背景
有一句话“小明和小龙是好朋友”,我想分析其中谁是人,我想分析他们的关系等多种需求,那么我们应该如何处理,如果为每一个关系都进行判断?显然不合适,我们可以将二者的关系进行抽象处理,然后就是实现多种关系规则,最后由规则解释你输入的话。解释器模式(Interpreter Pattern)提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
二、通常做法
AbstractExpression声明一个为抽象语法树中所有节点所共享的解释接口。
TerminalExpression表示终结符表达式,实现文法中终结符相关联的所有解释操作。
NonterminalExpression表示非终结符表达式,实现文法中所有非终结符的解释操作。
Context包含解释器外的一些全局信息。
Client构建语法树并调用解释器。
三、实例
1、构建一个抽象表达
namespace InterpreterPattern { public interface IExpress { bool Interpret(string context); } }
2、构建终结语法
namespace InterpreterPattern { public class TerminalExpress:IExpress { private string _data; public TerminalExpress(string data) { _data = data; } public bool Interpret(string context) { if (context.Contains(_data)) { return true; } return false; } } }
3、构建“与”语法
namespace InterpreterPattern { public class AndExpression : IExpress { private IExpress _expr1 = null; private IExpress _expr2 = null; public AndExpression(IExpress expr1, IExpress expr2) { _expr1 = expr1; _expr2 = expr2; } public bool Interpret(string context) { return _expr1.Interpret(context) && _expr1.Interpret(context); } } }
4、构建“或
namespace InterpreterPattern { public class OrExpression: IExpress { private IExpress _expr1 = null; private IExpress _expr2 = null; public OrExpression(IExpress expr1, IExpress expr2) { _expr1 = expr1; _expr2 = expr2; } public bool Interpret(string context) { return _expr1.Interpret(context) || _expr1.Interpret(context); } } }
5、构建解释器
namespace InterpreterPattern { public static class Translator { //规则:Robert 和 John 是男性 public static IExpress GetMaleExpression() { IExpress robert = new TerminalExpress("Robert"); IExpress john = new TerminalExpress("John"); return new OrExpression(robert, john); } //规则:Julie 是一个已婚的女性 public static IExpress GetMarriedWomanExpression() { IExpress julie = new TerminalExpress("Julie"); IExpress married = new TerminalExpress("Married"); return new AndExpression(julie, married); } } }
6、客户端调用
namespace InterpreterPattern { class Program { static void Main(string[] args) { IExpress isMale = Translator.GetMaleExpression(); IExpress isMarriedWoman = Translator.GetMarriedWomanExpression(); Console.WriteLine("John is male? " + isMale.Interpret("John")); Console.WriteLine("Julie is a married women? "+ isMarriedWoman.Interpret("Married Julie")); Console.ReadKey(); } } }
四、设计模式分析
优点: 1、可扩展性比较好,灵活。
2、增加了新的解释表达式的方式。
3、易于实现简单文法。
缺点: 1、可利用场景比较少。
2、对于复杂的文法比较难维护。
3、解释器模式会引起类膨胀。
4、解释器模式采用递归调用方法。