Charpter27 解释器模式
Posted yb-blogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Charpter27 解释器模式相关的知识,希望对你有一定的参考价值。
解释器模式简介
解释器模式(interpreter),给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示解释语言中的句子。
解释器模式需要解决的是,如果一个特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决问题。比如说正则表达式就是利用给解释器来模式实现的。
通常当有一个语言需要解释执行,并且你可将改语言中的句子表示为一个抽象语法树时,可实用解释器模式。
解释器模式的好处是可以很容易地改变和扩展文法,因为该模式实用累的表示文法准则,你可实用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中的各个节点的类的实现大体类似。这些类都易于直接编写。
解释器的不足之处,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。
解释器模式UML类图
C++代码实现
具体解释模式的内Interpt的的细节可忽略,不同的解释器为达到解释的目的,要根据一定的规则进行解释。具体规则与此设计模式无关。
// PlayContext 类 #ifndef _PLAYCONTEXT_HPP #define _PLAYCONTEXT_HPP #include<string> using namespace std; class PlayContext{ public: PlayContext(const string& str):context(str){} string getContext(){ return context; } void setContext(string str){ context = str; } private: string context; }; #endif
// Expression类 #ifndef _EXPRESSION_HPP #define _EXPRESSION_HPP #include"playcontext.hpp" class Expression{ public: void interpret(PlayContext* context){ if(context && context->getContext().size() != 0){ string playKey = context->getContext().substr(0,1); context->setContext(context->getContext().substr(1)); string::size_type pos; // get the index postion after stod function call. double playValue = stod(context->getContext(),&pos);//transfer the front substr to double; excute(playKey, playValue); if(pos+1 < context->getContext().size()){ context->setContext(context->getContext().substr(pos+1)); } else{ context->setContext(""); } } else{ //do nothing; } } virtual void excute(string key, double value) = 0; }; #endif
// Note类 #ifndef _NOTE_HPP #define _NOTE_HPP #include<iostream> #include"expression.hpp" using namespace std; class Note : public Expression{ public: virtual void excute(string key, double val) override { string note; if("C" == key ){ note = "1"; } else if("D" == key){ note = "2"; } else if("E" == key){ note = "3"; } else if("F" == key){ note = "4"; } else if("G" == key){ note = "5"; } else if("A" == key){ note = "6"; } else if("B" == key){ note = "7"; } else{ // do nothing } cout << note << " "; } }; #endif
//Scale类 #ifndef _SCALE_HPP #define _SCALE_HPP #include<iostream> #include"expression.hpp" using namespace std; class Scale : public Expression{ public: virtual void excute(string key, double val)override{ string scale; switch((int)val){ case 1: scale = "base"; break; case 2: scale = "mediant"; break; case 3: scale = "treble"; break; default: break; } cout << scale << " "; } }; #endif
// MyException类,只是为了异常处理,与设计模式无关 #ifndef _MYEXCEPTION_HPP #define _MYEXCEPTION_HPP #include<exception> #include<string> #include<cstring> class MyException : public std::exception{ public: MyException(const std::string& str){ char pre[] = "no this charactor ‘"; strcpy(val,pre); if(str.size() < sizeof(val)-strlen(pre)){ strcat(val,str.c_str()); } else{ strncat(val,str.c_str(),sizeof(val) - strlen(pre) -2); } strcat(val,"‘"); } virtual const char* what(){ return val; } private: char val[100]; }; #endif
// 客户端代码 #include<iostream> #include"playcontext.hpp" #include"note.hpp" #include"scale.hpp" #include"myexception.hpp" using namespace std; int main(){ PlayContext* context = new PlayContext( "O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 " ); try{ while(context && (context->getContext()!="") && context->getContext().size() != 0){ string str = context->getContext().substr(0, 1); Expression* exp = nullptr; if("O" == str){ exp = new Scale(); } else if("C" == str || "D" == str || "E" == str || "F" == str || "G" == str || "A" == str || "B" == str || "P" == str){ exp = new Note(); } else{ throw(new MyException(str)); } if(exp){ exp->interpret(context); } } }catch(MyException*e){ cout << e->what()<<endl; getchar(); } catch(...){ cout << "Other exception occurs"<<endl; getchar(); } getchar(); return 0; }
以上是关于Charpter27 解释器模式的主要内容,如果未能解决你的问题,请参考以下文章