设计模式--解释器模式C++实现
1定义
给定一门语言,定义他的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子
2类图
角色分析
AbstractExpression抽象解释器,具体的解释任务由各个实现类完成,具体的解释器分别由TerminalExpression和NonterminalExpression完成
TerminalExpression终结符表达式,实现与文法中的元素相关的解释操作,通常一个解释器模式中只能有一个终结符表达式,但有多个实例,敌营不同的终结符
NonterminalExpression非终结符,文法中的每条规则对应一个非终结表达式。
Context环境角色,
3实现
#pragma once #include<stack> #include<iostream> using namespace std; class Object; class Context; //抽象表达式 //抽象表达式是生成语法集合/语法树的关键,每个语法集合完成指定语法解析任务,通过递归调用方式完成 class Expression { public: virtual Object* interpreter(Context *ctx) = 0 { cout << "If you Can, you Don't" << endl; return NULL; }; }; //终结符表达式简单,主要处理场景元素和数据的转换 //终结符表达式 class TerminalExpression :public Expression { Object* interpreter(Context*ctx) { cout << "TerminalExpression::interpreter" << endl; return NULL; } }; //每个非终结符表达式都表示一个文法规则,每个文法规则又只关心周边文法规则的结果,所以就会有递归调用而存在 //非终结符表达式 class NonterminalExpression :public Expression { public: NonterminalExpression(Expression* x1, ...) { for (int i = 0; i < 4; ++i) { _st.push(x1); } } Object *interpreter(Context*ctx) { //核心支出在于这里。。进行文法处理,并且产生递归调用 //if(typeid().name() != "TerminalExpression") //递归调用 //文法处理 while (!_st.empty()) { Expression* tp = _st.top(); _st.pop(); cout << "NoterminalExpression::interpreter" << endl; tp->interpreter(ctx); } return NULL; } private: stack <Expression*> _st; }; class Context{ }; class Client { public: void operator()() { Context *ctx = new Context(); stack<Expression*> st; for (int i = 0; i < 5; ++i) { //进行语法判断,并且产生递归调用 st.push(new TerminalExpression()); st.push(new NonterminalExpression(new TerminalExpression())); } //for (int i = 0; i < 5; ++i) //{ // //进行语法判断,并且产生递归调用 // st.push(new NonterminalExpression(new TerminalExpression())); // st.push(new TerminalExpression()); //} //产生一个完整的语法树,由各个具体的语法分析进行解析 Expression *exp = st.top(); exp->interpreter(ctx); } };
4应用
①优点:是一个简单的语法分析工具,扩展性良好,修改语法只需要修改相对应的非终结符表达式就可以了,扩展语法只需要增加非终结符类即可
②缺点
解释器模式引起类膨胀
采用递归调用方式
效率问题,循环和引用太多
③使用场景
重复发生的事情可以用解释器模式(日志分析等)
一个简单语法需要解释的场景