设计模式十六:Interpreter(解释器)——类行为型模式
Interpreter(解释器)——类行为型模式
1.意图
给定一个语言,定义它的一种文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
2.动机
如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式描述了如何让为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这个句子。
3.适用性
当有一个语言需要解释执行,并且你可以将该语言中的一个句子表示为一个抽象语法树时,可使用解释器模式,而当存在以下情况时该模式的效果最好:
1)该文法简单,对于复杂的文法,文法的类层次变得庞大而无法管理。此时语法分析程序生成器这样的工具是更好的选择。他们无需构建抽象语法树就可以解释表达式,这样可以节省空间还可以节省时间。
2)效率不是一个关键问题,最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将他们转换成另一种形式。但即使在这种情况下,转换器仍可用解释器模式实现,该模式仍是可用的。
4.结构

参考:http://www.cnblogs.com/jqbird/archive/2011/09/07/2169566.html
5.参与者
AbstractExpression抽象表达式
声明一个抽象的解释操作,这个接口为语法树中所有的节点所共享
TerminalExpression终结符表达式
实现与文法中的终结符相关联的解释操作
一个句子中的每个终结符需要该类的一个实例
NonterminalExpression非终结符表达式
对文法中的每一条规则都需要一个类
为每个符号都维护一个AbstractExpression类型的实例变量
为文法中的非终结符实现解释操作,一般解释操作需要递归地调用表示所有对象的解释操作
Context上下文
包含解释器之外的一些全局信息
Client客户
构建(或者被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成
6.协作
1)client构建一个句子,是NonterminalExpression和TerminalExpression的实例的一个抽象语法树,然后初始化上下文并调用解释操作。
2)每一非终结符表达式节点定义相应子表达式的解释操作。而各个终结符表达式的解释操作构成了递归的基础
3)每一个节点的解释操作用上下文来存储和访问解释器的状态。
7.效果
1)易于扩展和改变文法
2)易于实现文法
3)复杂的文法难以维护
4)增加了新的解释表达式的方式
8.实现
1)创建抽象语法树
解释器模式不涉及到语法分析。抽象语法树可以用一个表驱动的语法分析程序来生成,也可以用手写的语法分析程序来创建,或者直接由client提供。
2)定义解释操作
并不一定要在表达式类中定义解释操作
3)与Flyweight模式共享终结符
9.代码实例
参考http://www.cnblogs.com/mayvar/archive/2011/09/08/wanghonghua_201109080339.html
罗马字符转换为十进制数字:
Expression抽象类:抽象表达式,声明一个抽象的解释器操作,这个抽象类为抽象语法树中所有的节点所共享。
ThousandExpression类:用来核对罗马字符中的 M ;
HundredExpression类:用来核对罗马字符中的C, CD, D or CM;
TenExpression类:用来核对罗马字附中的X, XL, L and XC;
OneExpression类:用来核对罗马字附中的I, II, III, IV, V, VI, VI, VII, VIII, IX。
#include<iostream> #include<string> #include<list> using namespace std; class context { public: string input; int output; context(string in) { input = in; output=0; } string getInput() { return input; } void setInput(string s) { input = s; } int getOutput() { return output; } void setOutput(int m) { output = m; } }; class Expression { public: void Interpret(context *c) { cout<<"the context is "<<c->getInput()<<endl; if(c->getInput().length() == 0) return; if(c->getInput().find(Nine()) == 0) { cout<<"we got "<<Nine()<<" "<<Multiplier()<<endl; c->setOutput(c->getOutput()+(9*Multiplier())); c->setInput(c->getInput().substr(2)); } else if(c->getInput().find(Four()) == 0) { cout<<"we got "<<Four()<<" "<<Multiplier()<<endl; c->setOutput(c->getOutput()+(4*Multiplier())); c->setInput(c->getInput().substr(2)); } else if(c->getInput().find(Five()) == 0) { cout<<"we got "<<Five()<<" "<<Multiplier()<<endl; c->setOutput(c->getOutput()+(5*Multiplier())); c->setInput(c->getInput().substr(1)); } while(c->getInput().find(One()) == 0) { cout<<"we got "<<One()<<" "<<Multiplier()<<endl; c->setOutput(c->getOutput()+(1*Multiplier())); c->setInput(c->getInput().substr(1)); } } virtual string One(){return "";}; virtual string Four(){return "";}; virtual string Five(){return "";}; virtual string Nine(){return "";}; virtual int Multiplier(){return 0;}; }; class ThousandExpression:public Expression { public: string One(){return "M";} string Four(){return " ";} string Five(){return " ";} string Nine(){return " ";} int Multiplier(){return 1000;} }; class HundredExpression:public Expression { public: string One(){return "C";} string Four(){return "CD";} string Five(){return "D";} string Nine(){return "CM";} int Multiplier(){return 100;} }; class TenExpression:public Expression { public: string One(){return "X";} string Four(){return "XL";} string Five(){return "L";} string Nine(){return "XC";} int Multiplier(){return 10;} }; class OneExpression:public Expression { public: string One(){return "I";} string Four(){return "IV";} string Five(){return "V";} string Nine(){return "IX";} int Multiplier(){return 1;} }; int main() { string str = "MCMXXVIII"; context *con = new context(str); list<Expression *> tree ; tree.push_back(new ThousandExpression()); tree.push_back(new HundredExpression()); tree.push_back(new TenExpression()); tree.push_back(new OneExpression()); for(list<Expression *>::iterator ite=tree.begin(); ite!=tree.end();ite++) { (*ite)->Interpret(con); } cout<<con->getOutput()<<endl; system("pause"); }
运行结果:
10.相关模式
composite模式
抽象语法树是一个符合模式的实例
flyweight模式
说明了如何在抽象语法树中共享终结符
iterator
解释器可用迭代器遍历该结构
visitor
可以用来一个类中维护抽象语法树中的各个节点的行为
浙公网安备 33010602011771号