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

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博客

相关推荐
点云SLAM5 分钟前
C++内存泄漏检测之Windows 专用工具(CRT Debug、Dr.Memory)和Linux 专业工具(ASan 、heaptrack)
linux·c++·windows·asan·dr.memory·c++内存泄漏检测·c++内存管理
浅念-17 分钟前
C语言小知识——指针(3)
c语言·开发语言·c++·经验分享·笔记·学习·算法
无限进步_2 小时前
【C++】大数相加算法详解:从字符串加法到内存布局的思考
开发语言·c++·windows·git·算法·github·visual studio
C+-C资深大佬2 小时前
C++ 数据类型转换是如何实现的?
开发语言·c++·算法
羞儿3 小时前
Agent设计模式与工程化
设计模式·知识图谱·agent·rag·mcp·指导开发
oioihoii4 小时前
回归测试:软件演进中的质量守护神与实践全指南
c++
十五年专注C++开发4 小时前
CMake基础: 在release模式下生成调试信息的方法
linux·c++·windows·cmake·跨平台构建
点云SLAM5 小时前
C++(C++17/20)最佳工厂写法和SLAM应用综合示例
开发语言·c++·设计模式·c++实战·注册工厂模式·c++大工程系统
Q741_1475 小时前
C++ 队列 宽度优先搜索 BFS 力扣 662. 二叉树最大宽度 每日一题
c++·算法·leetcode·bfs·宽度优先
csdn_aspnet5 小时前
C++跨平台开发:工程难题与解决方案深度解析
c++