意图:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
适用:
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。
而当存在以下情况时该模式效果最好:
1、该文法相对简单。对于复杂的文法, 文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。它们无需构建抽象语法树即可解释表达式, 这样可以节省空间而且还可能节省时间。
2、效率不是一个关键问题最高效的解释器通常不是通过直接解释语法分析树实现的, 而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下, 转换器仍可用解释器模式实现, 该模式仍是有用的。
参与者:
AbstractExpression
TerminalExpression
Context
Client
效果:
1、易于改变和扩展文法;
2、易于实现文法;
3、增加了新的解释表达式的方式,可通过访问者模式创建新的解释表达式的方式;
缺点:
复杂的文法难于维护,文法非常复杂时,可使用语法分析程序或编译器生成器更合适;
实现:
1、创建抽象语法树:该模式不涉及语法分析,从而不必涉及到语法树的创建。抽象语法树的创建可以通过client,亦可由表驱动的语法分析程序生成或手写的(递归下将法)语法分析程序生成;
2、定义解释操作:解释操作并不一定要放到表达式类中,如果经常需要添加一种操作,可以将其作为一个访问者;
3、通过享元模式共享终结符:终结符通常不存储它们在抽象语法树中的位置信息;
相关:Composite[一般用其表示]、Flyweight[共享终结符点]、Iterator[迭代器遍历结点]与Visitor[实现行为]
延伸:
Microsoft:我尝试在微软的框架中寻找该模式的应用,CodeDom与XMLDocument均只是用来表示文档对象模型,并没有采用解释器模式。关于Linq中的Expression是否是采用解释器模式,我也没有仔细分析,毕竟Linq文法本身属性框架内的东西,微软没有必要将相关细节public,然而从实现上来说,完全可能基于解释器模式。在Linq中的Expression实现上,文法结构树可通过静态成员来实现,Expression本身可用来表示一个文法实例上下文(Context)。Reduce可作为解释器的一个行为。
Sysnet:
C#
下面一段C#代码用来进行将字符串中的相关替代符替换成对象或xml结点值,其语法描述大值如下:
beginstring
@#!
{.tostring()}%原义字符%
@#^
%原义字符%{xpath表达式}
#@
#@
endstring
这是其中一段代码:
public interface IStringExpressionInterpreter
{
void Interpreter(IStringContext context, ExpressionDocument document);
}
/// <summary>
/// 解析总的表达式
/// </summary>
class ExpressionInterpreter : IStringExpressionInterpreter
{
static StringInterpreter StringInterpreter = new StringI