設計模式-解釋器模式Interpreter(對象行爲型)

一、概述

解釋器模式是一種按照規定語法進行解析的方案。給定一門語言,定義它的文法的一種表示,並定義一個解釋器,該解釋器使用該表示來解釋語言中的句子。

二、類圖

AbstractExpression爲抽象解釋器

TerminalExpression爲終結符表達式。實現與文法中的元素相關聯的操作,通常一個解釋器模式中只有一個終結符表達式,但有多個實例,對應不同的終結符。

NonterminalExpression爲非終結符表達式。文法中的每條規則對應於一個非終結表達式,具體到下面的實例就是加減法則分別對應到AddExpression和SubExpression兩個類。非終結符表達式根據邏輯的複雜程度而增加,原則上每個文法規則都對應一個非終結符表達式。

Context爲環境角色。

三、示例

//test.h
#pragma once

class Expression
{
public:
	virtual int Interpreter(map<string, int>& mapValueList) = 0;
};

class VarExpression : public Expression
{
public:
	VarExpression(string sVarName);

public:
	virtual int Interpreter(map<string, int>& mapValueList);

private:
	string m_sVarName;
};

class AddSymbolExpression : public Expression
{
public:
	AddSymbolExpression(Expression* pLeftExpression, Expression* pRightExpression);

public:
	virtual int Interpreter(map<string, int>& mapValueList);

private:
	Expression* m_pLeftExpression;
	Expression* m_pRightExpression;
};

class DelSymbolExpression : public Expression
{
public:
	DelSymbolExpression(Expression* pLeftExpression, Expression* pRightExpression);

public:
	virtual int Interpreter(map<string, int>& mapValueList);

private:
	Expression* m_pLeftExpression;
	Expression* m_pRightExpression;
};

class Calculator 
{
public:
	void SetExpressionString(string sExpressionString);
	int GetResult(map<string,int> mapValueList);

private:
	Expression* m_pExpression;
};
//test.cpp
#include <stdio.h>
#include <iostream>
#include <map>
#include <string>
#include <stack>
using namespace std;

#include "Test.h"

VarExpression::VarExpression(string sVarName)
	:m_sVarName(sVarName)
{

}

int VarExpression::Interpreter(map<string, int>& mapValueList)
{
	map<string, int>::iterator it = mapValueList.find(m_sVarName);
	if (it != mapValueList.end())
	{
		return it->second;
	}
	return -1;
}

AddSymbolExpression::AddSymbolExpression(Expression* pLeftExpression, Expression* pRightExpression)
	:m_pLeftExpression(pLeftExpression),m_pRightExpression(pRightExpression)
{

}

int AddSymbolExpression::Interpreter(map<string, int>& mapValueList)
{
	return m_pLeftExpression->Interpreter(mapValueList) + m_pRightExpression->Interpreter(mapValueList);
}

DelSymbolExpression::DelSymbolExpression(Expression* pLeftExpression, Expression* pRightExpression)
	:m_pLeftExpression(pLeftExpression), m_pRightExpression(pRightExpression)
{

}

int DelSymbolExpression::Interpreter(map<string, int>& mapValueList)
{
	return m_pLeftExpression->Interpreter(mapValueList) - m_pRightExpression->Interpreter(mapValueList);
}

void Calculator::SetExpressionString(string sExpressionString)
{
	std::stack<Expression*> stackExpressionList;
	Expression* pLeftExpression;
	Expression* pRightExpression;
	for (int i = 0; i < sExpressionString.size(); i++)
	{
		char cTem = sExpressionString.at(i);
		switch (cTem)
		{
		case '+':
			{
				pLeftExpression = stackExpressionList.top();
				stackExpressionList.pop();
				char buf[5] = { 0 };
				sprintf(buf, "%c", sExpressionString.at(++i));
				pRightExpression = new VarExpression(buf);
				stackExpressionList.push(new AddSymbolExpression(pLeftExpression, pRightExpression));
			}
			break;
		case '-':
		{
			pLeftExpression = stackExpressionList.top();
			stackExpressionList.pop();
			char buf[5] = { 0 };
			sprintf(buf, "%c", sExpressionString.at(++i));
			pRightExpression = new VarExpression(buf);
			stackExpressionList.push(new DelSymbolExpression(pLeftExpression, pRightExpression));
		}
			break;
		default:
		{
			char buf[5] = { 0 };
			sprintf(buf, "%c", sExpressionString.at(i));
			stackExpressionList.push(new VarExpression(buf));
		}
			break;
		}
	}
	m_pExpression = stackExpressionList.top();
}

int Calculator::GetResult(map<string, int> mapValueList)
{
	return m_pExpression->Interpreter(mapValueList);
}

int main()
{
	Calculator cal;
	cal.SetExpressionString("a+b-c+d");
	map<string, int> mapValueList;
	mapValueList["a"] = 100;
	mapValueList["b"] = 55;
	mapValueList["c"] = 84;
	mapValueList["d"] = 1;

	int nResult = cal.GetResult(mapValueList);
	cout << "the result is: " << nResult << endl;

	getchar();

	return 0;
}

四、解釋器模式的優點

解釋器模式是一個簡單的語法分析工具,它的優點就是擴展性,修改語法規則只要修改相應的非終結符表達式即可,若擴展語法,則只要增加非終結符類就可以了。

五、解釋器模式的缺點

(1)引起類膨脹,每個語法都要產生一個非終結符表達式,語法規則比較複雜時,就會產生大量的類

(2)解釋器模式採用遞歸調用

每個非終結符表達式只關心與自己有關的表達式,每個表達式需要知道最終的結果,必須一層層遞歸。遞歸不僅使程序調試複雜,而且還會降低效率。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章