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

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

相关推荐
qz_Serene1 小时前
C++:类和对象(上)
开发语言·c++
郝学胜-神的一滴2 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
hetao17338373 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
间歇性努力持续性发呆的野生快乐选手5 小时前
栈的性质(进栈,出栈,访问)
数据结构·c++
旖旎夜光6 小时前
LeetCode 904:水果成篮(滑动窗口) —— 题解
数据结构·c++·算法·leetcode·滑动窗口
workflower6 小时前
例二:某汽车制造企业深度融合AI智能体,构建园区网络的智能运维体系
人工智能·机器学习·设计模式·机器人·云计算·汽车·制造
乐观勇敢坚强的老彭7 小时前
C++ 竞赛常用算法模板速查表
开发语言·c++·算法
ly76897 小时前
Java 设计模式详解:从原则到 23 种经典模式
java·开发语言·设计模式
我变成萤火虫8 小时前
河南萌新联赛2026第(三)场:郑州轻工业大学
数据结构·c++·算法·贪心算法·stl·深度优先·哈希算法
buhuizhiyuci8 小时前
【Linux 篇】数字世界的水流蓄水池 —— IO 缓冲区机制深度实战解析
linux·运维·服务器·c++