1. 程式人生 > >設計模式C++版:第十九式直譯器模式

設計模式C++版:第十九式直譯器模式

直譯器模式:給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該解釋語言中的句子。比如配置檔案,比如正則表示式,比如瀏覽器對HTML。當有一個語言需要解釋執行,並且可將該語言中的句子表示為一個抽象語法樹時,可以使用直譯器模式。

#pragma once 
#include<stdio.h>
#include<string>
using std::string;

//文字類
class Context
{
public:
	void  settext(const string& text)
	{
		this->m_text = text;
	}

	string  gettext()
	{
		return m_text;
	}

private:
	string m_text;
};


// 解釋類

class  Expression
{
public:
	virtual ~Expression(){ }
	void interpret(Context &context)
	{
		if (context.gettext().length()==0)
		{
			return;
		}
		else
		{
			string key = context.gettext().substr(0, 1);
			context.settext(context.gettext().substr(2));
			double value = atof(context.gettext().substr(0,context.gettext().find(' ')+1).c_str());
			context.settext(context.gettext().substr(context.gettext().find(' ')+1));
			excute(key, value);
		}
	}
	virtual void excute(const string& key, double value){ }
};


class Note:public Expression
{
public:
	virtual void excute(const string& key, double value)
	{
		char not = key.at(0);
		switch(not)
		{
		case'C':
			not = '1';
			break;

		case'D':
			not = '2';
			break;

		case'E':
			not = '3';
			break;
		case'F':
			not = '4';
			break;
		case'G':
			not = '5';
			break;
		case'A':
			not = '6';
			break;
		case'B':
			not = '7';
			break;
		default:
			break;
		}

		printf("%c ", not);
	}
};

class Scale :public Expression
{
public:
	virtual void excute(const string& key, double value)
	{
		string  key0 = "";
		int val = value;
		switch (val)
		{
		case 1:
			key0 ="低音";
			break;
		case 2:
			key0 = "中音";
			break;
		case 3:
			key0 = "高音";
			break;
		default:
			break;
		}

		printf("%s ", key0.c_str());
	}
};

int main()
{
	Context context;
	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 ");

	while (context.gettext().length() > 0)
	{
		string str = context.gettext().substr(0, 1);
		char not = str.at(0);
		Expression * expr = nullptr;
		switch (not)
		{
		case 'C':
		case 'D':
		case 'E':
		case 'F':
		case 'G':
		case 'A':
		case 'B':
		case 'P':
			expr = new Note;
			break;
		case 'O':
			expr = new Scale;
			break;
		default:
			break;
		}
		expr->interpret(context);   //引用

		delete expr;
		expr = nullptr;
	}

	printf("\n");
	return 0;
}

說到底如果狀態和型別多的時候,switch case 還是比狀態等模式使用方便。效率高,還清晰,當然使用陣列也可以。