行为型模式--Interpreter(解释器)类行为型模式
一. 意图
给定一个语言, 定义它的文法的一种表示, 并定义一个解释器, 这个解释器使用该表示来解释语言中的句子.
二. 适用性
如果一种特定类型的问题发生的频率足够高, 那么可能就值得将该问题的各个实例表述为一个简单语言中的句子. 这样就可以构建一个解释器, 该解释器通过解释这些句子来解决该问题.
当有一个语言需要解释执行, 并且你可将该语言中的句子表示为一个抽象语法树时, 可使用解释器模式.
三. 模式结构
图1
四. 角色说明
AbstractExpression(抽象表达式)
—声明一个抽象的解释操作, 这个接口为抽象语法树中所有的节点所共享.
TerminalExpression(终结符表达式)
—实现与文法中的终结符相关联的解释操作.
—一个句子中的每个终结符需要该类的一个实例.
NonTerminalExpression(非终结符表达式)
—对文法中的每一条规则都对应一个NonTerminalExpression类。
—为从R1到Rn的每个符号都维护一个AbstractExpression类型的实例变量。
—为文法中的非终结符实现解释(Interpret)操作. 解释(Interpret)一般要递归地调用表示R1到Rn的那些对象的解释操作.
Context(上下文)
—包含解释器之外的一些全局信息.
Client(客户)
—构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树. 该抽象语法树由NonTerminalExpression和TerminalExpression的实例装配而成.
—调用解释操作.
协作
Client构建(或被给定)一个句子, 它是NonterminalExpression和TerminalExpression的实例的一个抽象语法树. 然后初始化上下文并调用解释操作.
a. 每一非终结符表达式节点定义相应子表达式的解释操作。而各终结符表达式的解释操作构成了递归的基础.
b. 每一节点的解释操作用上下文来存储和访问解释器的状态.
五. 说明
1. 易于改变和扩展文法, 因为每一个规则都被封装到一个类中.
2. 也易于实现文法, 定义抽象语法树中各个节点的类的实现大体类似.
3. 复杂的文法难以维护, 如果有1万个文法, 你需要定义1万个类, 这明显不好维护.
4. Interpreter和Composite模式在实现上有许多相通的地方(就是有一个递归).
5. 创建抽象语法树 解释器模式并未解释如何创建一个抽象的语法树(就是并没有对给出的字符串进行分离出对应的文法).
(例如: 1+3-4, Interpreter模式可以对这条表达式求值, 但1+3-4中每一项的分离Interpreter并没有去分析.)
6. 定义解释操作并不一定要在表达式类中定义解释操作(在Interpret函数中传递给专门的类去解析).
7. 可以使用Flyweight模式共享终结符. 终结节点通常不存储关于它们在抽象语法树中位置的信息. 在解释过程中, 任何它们所需要的上下文信息都由父节点传递给它们. 因此在共享的(内部的)状态和传入的(外部的)状态区分得很明确, 这就用到了Flyweight模式.
六. 我的理解:
1. 书中例子
expression ::= literal | alternation | sequence | repetition | '(' expression ')'
alternation ::= expression '|' expression
sequence ::= expression '&' expression
repetition ::= expression '*'
literal ::= 'a' | 'b' | 'c' | ... {'a' | 'b' | 'c' | ...}*
符号expression是开始符号, literal是定义简单字的终结符.
表达式raining & (dogs | cats) *的语法树是:
图2
假设 raining & (dogs | cats) *中 raining 值为true; dogs值为false; cats值为false, 那么表达式raining & (dogs | cats) *的值就是true & (false | false) 那就是false. Interpreter模式的作用就是能方便的求出给定语法规则的表达式的值. (Interpreter模式不解析表达式, 或者说不对语法解析, 例如raining & (dogs | cats) *字符串中的raining 怎样提取出来的, 不是Interpreter模式做的)
2. 例如我定义一个加减法则
// 表达式
expression ::= literal | PlusSign | MinusSign | '(' expression ')'
// 加号
PlusSign ::= '+'
// 减号
MinusSign ::= '-'
// 终结符
literal ::= '0' | '1' | '2' | ... {'0' | '1' | '2' | ... }
表达式1 + (3 - 1)的语法树就是:
Expression >>>>>literal PlusSign (Expression)>>>>literal PlusSign (literal MinusSign literal )
表达式1 + 2 - (3 - 1)的语法树有两棵分别是:
Expression >>>>>Expression MinusSign (Expression)>>>>literal PlusSign literal MinusSign (literal MinusSign literal )
Expression >>>>>literal PlusSign Expression>>>>literal PlusSign literal - (Expression)>>>literal PlusSign literal MinusSign (literal MinusSign literal )
很明显: 完全展开后, 它们是一样的(殊途同归而已)
3. 对语法树求值可以使用Interpreter模式.
七. 相关模式:
Composite模式: 抽象语法树是一个复合模式的实例.