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

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

相关推荐
郝学胜_神的一滴14 小时前
CMake 034:生成器表达式:解耦构建时序、精简分支逻辑的终极利器
c++·cmake
咖啡八杯1 天前
GoF设计模式——中介者模式
java·后端·spring·设计模式
见过夏天1 天前
C++ 基础入门完全指南
c++
胡萝卜术2 天前
从“分数打架”到“排名投票”:为什么你的ChatBI必须用RRF?
算法·设计模式·面试
亦暖筑序2 天前
Java 8老系统Browser Agent实战:三层拦截把AI操作后台变成可审计流程
java·后端·设计模式
用户805533698033 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK3 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
卷无止境4 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端
卷无止境4 天前
OpenMPI、MPICH 与 OpenMP:关系、核心概念与架构全解
c++·后端
郝学胜_神的一滴5 天前
CMake 30:循环语法全解|foreach_while双循环精讲、迭代技巧与实战避坑指南
c++·cmake