大话设计模式
1 解释器模式(interpreter)结构图
2 对解释器模式的一些解释
概念:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。【DP】
也就是说如果一种特定类型的问题发生的概率足够高,那么可能就值得该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。【DP】
使用场景:当有一个语言需要解释执行,并且你可将改语言中的句子表示为一个抽象语法语树时,可以使用解释器模式。【DP】
优点:用了解释器模式,就意味着可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树种各个节点的类的实现大体类似,这些类都易于直接边写。
缺点:解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。
3 C++源代码实现
3.1 代码结构图
3.2 C++源代码
PlayContext.h
#ifndef _PLAYCONTEXT_H_
#define _PLAYCONTEXT_H_
#include<string>
using std::string;
//演奏内容类(context)
class PlayContext
{
private:
string text;
public:
void setText(const string &str);
string getText();
};
#endif
PlayContext.cpp
#include"PlayContext.h"
void PlayContext::setText(const string &text)
{
this->text = text;
}
string PlayContext::getText()
{
return this->text;
}
Expression.h
#ifndef _EXPRESSION_H_
#define _EXPRESSION_H_
#include<string>
using std::string;
class PlayContext;
//表达式类(AbstractExpression)
class Expression
{
public:
//此方法用于当前的演奏文本第一条命令获得命令字母和其参数值。
//例如“O 3 E 0.5 G 0.5 A 3”
//则palyKey为O,而playValue为3
void Interpret(PlayContext *context);
virtual void Excute(string key, double value) = 0;
};
//音符类(TerminalExpression)
class Note :public Expression
{
public:
void Excute(string key, double value) override;
};
//音阶类(TerminalExpression)
class Scale :public Expression
{
public:
void Excute(string key, double value) override;
};
//
#endif
#include"Expression.h"
#include"PlayContext.h"
#include<iostream>
#include<vector>
#include<sstream>
using std::cout;
using std::endl;
using std::stod;
using std::stringstream;
using std::vector;
void Expression::Interpret(PlayContext *context)
{
if (context->getText().empty())
return;
else
{
stringstream sst(context->getText());
vector<string> vec;
string s;
string buf;
while (sst >> buf)
vec.push_back(buf);
Excute(vec[0], stod(vec[1]));
vec.erase(vec.begin(), vec.begin() + 2);
for (auto it = vec.begin(); it != vec.end(); ++it)
{
s += *it;
if (it != vec.end() - 1)
s += " ";
}
context->setText(s);
}
}
void Note::Excute(string playKey, double playValue)
{
string note;
switch (playKey[0])
{
case 'C':
note = "1";
break;
case 'D':
note = "2";
break;
case 'E':
note = "3";
break;
case 'F':
note = "4";
break;
case 'G':
note = "5";
break;
case 'A':
note = "6";
break;
case 'B':
note = "7";
break;
default:
note = "";
break;
}
cout << note << " ";
}
void Scale::Excute(string playKey, double playValue)
{
string scale;
int num = static_cast<int>(playValue);
switch (num)
{
case 1:
scale = "低音";
break;
case 2:
scale = "中音";
break;
case 3:
scale = "高音";
break;
default:
scale = "";
break;
}
cout << scale << " ";
}
客户端Client.cpp
#include"Expression.h"
#include"PlayContext.h"
#include<iostream>
using std::cout;
using std::endl;
int main()
{
PlayContext context;
std::cout << "上海滩:" << std::endl;
context.setText("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* expression = nullptr;
while (context.getText().length()>0)
{
char c = context.getText()[0];
switch (c)
{
case 'O':
expression = new Scale();
break;
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'A':
case 'B':
case 'P':
expression = new Note();
break;
}
expression->Interpret(&context);
//delete expression;
}
system("pause");
}
上海滩:
中音 3 5 6 3 5 2 3 5 6 高音 1 中音 6 5 1 3 2 请按任意键继续. . .