大话设计模式27----解释器模式

大话设计模式


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

Expression.cpp
#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 请按任意键继续. . .







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值