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

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

相关推荐
看到我,请让我去学习1 小时前
OpenCV编程- (图像基础处理:噪声、滤波、直方图与边缘检测)
c语言·c++·人工智能·opencv·计算机视觉
xiaolang_8616_wjl9 小时前
c++文字游戏_闯关打怪2.0(开源)
开发语言·c++·开源
夜月yeyue9 小时前
设计模式分析
linux·c++·stm32·单片机·嵌入式硬件
收破烂的小熊猫~10 小时前
《Java修仙传:从凡胎到码帝》第四章:设计模式破万法
java·开发语言·设计模式
无小道10 小时前
c++-引用(包括完美转发,移动构造,万能引用)
c语言·开发语言·汇编·c++
FirstFrost --sy12 小时前
数据结构之二叉树
c语言·数据结构·c++·算法·链表·深度优先·广度优先
Tanecious.12 小时前
C++--map和set的使用
开发语言·c++
Yingye Zhu(HPXXZYY)12 小时前
Codeforces 2021 C Those Who Are With Us
数据结构·c++·算法
佛祖让我来巡山12 小时前
【工厂和策略设计模式妙用】解决接口选择与多重if-else 问题
设计模式·策略模式·工厂模式
liulilittle13 小时前
LinkedList 链表数据结构实现 (OPENPPP2)
开发语言·数据结构·c++·链表