C++设计模式——解释器模式(interpreter pattern)

一、原理讲解

1.1意图

给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

1.2应用场景

  • 文法简单。对于复杂的文法,文法的类层次变得庞大而无法管理;此时语法分析程序生成器这样的工具是更好的选择。它们无法构件抽象语法树即可解释表达式,这样可以节省空间而且还可能节省时间。
  • 效率不是关键问题。最高效的解释器通常不是通过直接解释语法分析树实现的,而是首先将它们转换成另一种形式。例如,正则表达式通常被转换成状态机。但即使在这种情况下,转换器也可用解释器模式实现,该模式仍然有用;

1.3结构图(UML图)

C++设计模式——解释器模式(interpreter pattern)_第1张图片

1.4代码实现步骤

a1 定义数据转换类Context,定义获取数据接口函数getValue(),以及定义转换数据map datas;
a2 定义表达式类Expression,定义一个解释器抽象接口函数int interpreter(Context*)=0,同时定义一个左右子树指针Expression left,Expression right;
a3 定义具体非终结符表达式类,比如乘法类MultiExpression,重写接口函数int interpreter(Context
);
a4 定义具体非终结符表达式类,比如除法类DivisionExpression,重写接口函数int interpreter(Context
);
a5 定义具体终结符表达式类,比如TerminalExpression,重写接口函数int interpreter(Context*)终止递归调用,同时定义成员变量(转换后的值,也就是键值对的值)int value;

二、实现代码

代码主要功能是实现一个乘法和除法运算,即 3*4/2==6.

  • InterpreterPattern.cpp
#include 
#include 

using namespace std;

#define DELETE(pointer) delete pointer; pointer=nullptr
const string key1 = string("s1");
const string key2 = string("s2");
const string key3 = string("s3");
const string key4 = string("s4");

class Context1
{
public:
	Context1(){
		datas[key1] = 1;
		datas[key2] = 2;
		datas[key3] = 3;
		datas[key4] = 4;
	}

	int getValue(string key) { 
		if (!datas.count(key))
		{
			return 0;
		}
		return datas[key];
	}

private:
	std::map<string, int> datas;
};

class Expression
{
public:	
	Expression(Expression *left, Expression *right) :left(left), right(right) { }
	
	virtual ~Expression() {
		if (left != nullptr)
		{
			DELETE(left);
			cout << "delete left" << endl;
		}
		if (right != nullptr)
		{
			DELETE(right);
			cout << "delete right" << endl;
		}
	}
	
	virtual int interpreter(Context1* context) = 0;

protected:
	Expression *left;
	Expression *right;
};

class MultiExpression : public Expression
{
public:
	MultiExpression(Expression *left, Expression *right) : Expression(left, right) { }

	int interpreter(Context1* context) override {
		if ((left == nullptr) || (right == nullptr))
		{
			return 0;
		}
		return left->interpreter(context) * right->interpreter(context);
	}
};


class DivisionExpression : public Expression
{
public:
	DivisionExpression(Expression *left, Expression *right) : Expression(left, right) { }

	int interpreter(Context1* context) override {
		if ((left == nullptr) || (right == nullptr))
		{
			return 0;
		}
		return left->interpreter(context) / right->interpreter(context);
	}
};

class TerminalExpression : public Expression
{
public:
	TerminalExpression(int value) : value(value), Expression(nullptr, nullptr) { }
	int interpreter(Context1* context) {
		return value;
	}

private:
	int value;
};

void doInterpreter() // 客户端client
{
	/*   3*4/2==6  对应语法树如下:	

	       /   (除法)
	      / \
	      *  2
		 / \
		3   4
	*/
	Context1 context;
	
	MultiExpression *multiExpression = new MultiExpression(new TerminalExpression(context.getValue(key3))
		, new TerminalExpression(context.getValue(key4))); // 终止节点作为叶子结点,非终止节点作为非叶子节点
	int mutil = multiExpression->interpreter(&context);
	cout << "mutil==" << mutil << endl;

	DivisionExpression *divisionExpression = new DivisionExpression(multiExpression
		, new TerminalExpression(context.getValue(key2))); // 乘法表达式作为左子树 / 右子树
	int division = divisionExpression->interpreter(&context); // 运行解释器
	cout << "division==" << division << endl;

	DELETE(divisionExpression);	
	// 这里注意,不能第二次释放divisionExpression,因为此时它是divisionExpression的左子树
	//,divisionExpression释放的时候会自动释放左右子树,也就是递归释放,最终只需要释放最后一次嵌套调用的就行
}
  • mian.cpp
#include 

using namespace std;

extern void doInterpreter();

int main()
{
	doInterpreter();

	system("pause");
	return 1;
}

C++设计模式——解释器模式(interpreter pattern)_第2张图片

三、总结

在本次乘除法代码实现中,解释器模式的核心思想是用叶子节点(也就是终止符类)作为值,而把非叶子节点(也就是非终止类)作为符号运行,综合起来形成一个表达式,然后进行计算int interpreter(Context *)。

3.1相关模式

  • Composite:抽象语法树是一个组合模式的实例;
  • Flyweight:说明了如何在抽象语法树中共享终结符;
  • Iterator:迭解释器可用一个迭代器遍历该结构;
  • Visitor:可用来在一个类中维护抽象语法树中各节点的行为;

四、参考内容

设计模式C++实现(20)——解释器模式
设计模式C++实现-解释器模式
C++设计模式之解释器模式
陈建忠设计模式(参考:哔哩哔哩C++设计模式!!!)
Erich Gamma,Richard Helm.《设计模式 可复用面向对象软件的基础》[M].机械工业出版社,2019:

你可能感兴趣的:(设计模式,设计模式,c++,解释器,interpreter,vs2019)