部分内容参考大话设计模式第27章;本实验通过C++语言实现。
一 基本原理
意图:给定一个语言,定义其文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
上下文:如果业务规则频繁变化,类似的模式不断重复出现,这种特定类型的变化发生的频率足够高,但效率不是关键。
能否抽象并表示一种简单的语法规则,这种语法能将各种变化表述为一种简单语言的句子,以应对这种频繁的变化?
解释器模式静态类图
AbstractExpression:声明一个抽象的解释操作,这个接口为抽象语法树中所有节点共享。
TerminalExpression:实现语法中的终结符的解释操作,一个句子中的每个终结符都需要该类的一个实例。
NonterminalExpression:语法中的每个规则R::=R1,R2,…,Rn都需要一个这样的类;R1,…,Rn中每个符号都需要该类的一个实例;实现语法中非终结符的解释操作,解释一般需要递归地调用R1,…,Rn的解释操作。
Context:解释器之外的全局信息。
Client:构建表示语法中一个特定的句子的抽象语法树,该抽象语法树由TerminalExpression和NonterminalExpression的实例装配而成;调用AbstractExpression的解释操作(Interpret)
测试代码:
#include <iostream>
#include <list>
#include <mutex>
#include <map>
#include <string>
using namespace std;
class Context{
public:
string input;
string getInput() const;
void setInput(const string &value);
string output;
string getOutput() const;
void setOutput(const string &value);
};
string Context::getInput() const
{
return input;
}
void Context::setInput(const string &value)
{
input = value;
}
string Context::getOutput() const
{
return output;
}
void Context::setOutput(const string &value)
{
output = value;
}
class AbstractExpression{
public:
virtual void Interpret(Context *context) = 0;
};
class TerminalExpression : public AbstractExpression{
// AbstractExpression interface
public:
void Interpret(Context *context)
{
(void)(context);
cout << "终端解释器" << endl;
}
};
class NonterminalExpression : public AbstractExpression{
// AbstractExpression interface
public:
void Interpret(Context *context)
{
(void)(context);
cout << "非终端解释器" << endl;
}
};
int main(void)
{
Context *c = new Context();
list<AbstractExpression*> mylist;
mylist.push_back(new TerminalExpression());
mylist.push_back(new NonterminalExpression());
mylist.push_back(new TerminalExpression());
mylist.push_back(new TerminalExpression());
list<AbstractExpression*>::iterator it;
for(it = mylist.begin();it != mylist.end();it++){
AbstractExpression *exp = *it;
exp->Interpret(c);
}
cout << "--end--" << endl;
return 0;
}
运行结果:
终端解释器
非终端解释器
终端解释器
终端解释器
--end--
二 音乐解释器实现
测试代码:
#include <iostream>
#include <list>
#include <mutex>
#include <map>
#include <string>
using namespace std;
//演奏内容类
class PlayContext{
public:
string text;
string playText;
string getText() const;
void setText(const string &value);
string getPlayText() const;
void setPlayText(const string &value);
};
string PlayContext::getPlayText() const
{
return playText;
}
void PlayContext::setPlayText(const string &value)
{
playText = value;
}
string PlayContext::getText() const
{
return text;
}
void PlayContext::setText(const string &value)
{
text = value;
}
//表达式类
class Expression{
public:
void Interpret(PlayContext *context){
if(context->playText.length() == 0){
return;
}else{
string playKey = context->playText.substr(0,1);
context->playText = context->playText.substr(2);
double platValue = stod(context->playText.substr(0,context->playText.find(" ")));
context->playText = context->playText.substr(context->playText.find(" ") + 1);
this->Excute(playKey,platValue);
}
}
virtual void Excute(string key,double value) = 0;
};
//音符类
class Note:public Expression{
// Expression interface
public:
void Excute(string key, double value)
{
(void)(value);
string note = "";
do{
if(key == "C"){
note = "1";
break;
}
if(key == "D"){
note = "2";
break;
}
if(key == "E"){
note = "3";
break;
}
if(key == "F"){
note = "4";
break;
}
if(key == "G"){
note = "5";
break;
}
if(key == "A"){
note = "6";
break;
}
if(key == "B"){
note = "7";
break;
}
}while(0);
cout << note << " ";
}
};
//音阶类
class Scale:public Expression{
// Expression interface
public:
void Excute(string key, double value)
{
(void)(key);
string scale = "";
switch ((int)(value)) {
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
default:
cout << "这里不对" << value << endl;
break;
}
cout << scale << " ";
}
};
//音速
class Speed:public Expression
{
// Expression interface
public:
void Excute(string key, double value)
{
string speed;
if(value < 500){
speed = "快速";
}else if(value >= 1000){
speed = "慢速";
}else{
speed = "中速";
}
cout << speed << " ";
}
};
int main(void)
{
PlayContext *c = new PlayContext();
cout << "上海滩" << endl;
c->playText = "T 500 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 ";
Expression *exp;
while(c->playText.length() > 0){
//cout << c->playText << endl;
string str = c->playText.substr(0,1);
if(str.length() == 0){
cout << "解析完毕" << endl;
break;
}
if(str == "O"){
exp = new Scale();
}else if(str == "T"){
exp = new Speed();
}else if(str == "C" || str == "D"
|| str == "E"|| str == "F"
|| str == "G"|| str == "A"|| str == "B"){
exp = new Note();
}
exp->Interpret(c);
}
cout << endl << "--end--" << endl;
return 0;
}
运行结果:
上海滩
中速 中音 3 5 6 3 5 2 3 5 6 高音 1 中音 6 5 1 3 2
--end--