解释器模式 行为型模式之五

1.定义

给定一个语言,定义它的文法的一种表示,并定义一个解释器。比如加减乘除在代码里是一种表示,我们需要翻译成可以阅读的数学公式,并且可以供用户输入数字得到输出结果。

2.组成结构

  1. 抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  2. 终结符表达式(Terminal Expression):是抽象表达式的子类,用来实现文法中与终结符相关的操作,文法中的每一个终结符都有一个具体终结表达式与之相对应。
  3. 非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,用来实现文法中与非终结符相关的操作,文法中的每条规则都对应于一个非终结符表达式。
  4. 上下文(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

我们将用示例代码来解释各个组成部分的意义。

3.示例代码

cpp 复制代码
#include <iostream>
#include <map>

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 Context
{
public:
	Context() {
		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);
		}
		if (right != nullptr)
		{
			DELETE(right);
		}
	}

	virtual int interpreter(Context* context) = 0;

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

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

	int interpreter(Context* 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(Context* 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(Context* context) {
		return value;
	}

private:
	int value;
};

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

		   /   (除法)
		  / \
		  *  2
		 / \
		3   4
	*/
	Context 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释放的时候会自动释放左右子树,也就是递归释放,最终只需要释放最后一次嵌套调用的就行
}

int main()
{
	doInterpreter();

	system("pause");
	return 1;
}

引用

C++设计模式------解释器模式(interpreter pattern)_c++interpreter模式-CSDN博客

相关推荐
John_ToDebug1 分钟前
Chrome 浏览器前端与客户端双向通信实战
前端·c++·chrome
scoone4 分钟前
ESP32开发中Kconfig ninja cmake 三者之间的关系
c++
Smile丶凉轩1 小时前
技术栈RabbitMq的介绍和使用
c++·分布式·rabbitmq
点云SLAM1 小时前
C++中string流知识详解和示例
开发语言·c++·istringstream·ostringstream·c++学习·stringstream·数据流操作
achene_ql9 小时前
select、poll、epoll 与 Reactor 模式
linux·服务器·网络·c++
SY师弟10 小时前
51单片机——计分器
c语言·c++·单片机·嵌入式硬件·51单片机·嵌入式
豪斯有话说11 小时前
C++_哈希表
数据结构·c++·散列表
real_metrix12 小时前
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
c++·迭代器·迭代器失效·erase
朝朝又沐沐12 小时前
基于算法竞赛的c++编程(18)string类细节问题
开发语言·c++·算法
hstar952712 小时前
三十四、面向对象底层逻辑-SpringMVC九大组件之FlashMapManager接口设计哲学
java·spring·设计模式·架构