设计模式-解释器模式

解释器模式通过创建表达式的派生类实现特定语法的解释。该模式将一个复杂的表达式分解成多个部分,每个部分对应一个类。当需要新增语法时,只需添加新的派生类即可。虽然方便扩展,但若语法复杂,可能导致大量类,增加维护难度。
摘要由CSDN通过智能技术生成

1. 解释器模式

一个表达式中有多个语法,每一个语法就是一个派生类,有一个特定的解释;
解释器模式是讲一个表达式根据语法分为多个派生类,并且对每一个派生类执行解释。
下面的代码是使用解释器模式求解"a+b-c", 思路是求得的值放在栈顶;


class Expression {
public:
	virtual int interpreter(map<string, int>& var) = 0;
	virtual ~Expression() {}
};


class VarExpression :public Expression {
private:
	string key;
public:
	VarExpression(const string& k) :key(k) {}
	virtual int interpreter(map<string, int>& var) {
		return var[key];
	}
	virtual ~VarExpression() {
		cout << "~VarExpression()" << endl;
	}
};

class SymbolExpression :public Expression {
protected:
	Expression* left;
	Expression* right;
public:
	SymbolExpression(Expression* l, Expression* r) :left(l), right(r) {}
	Expression* getLeft() {
		return left;
	}
	Expression* getRight() {
		return right;
	}
};

class AddExpression :public SymbolExpression
{
public:
	AddExpression(Expression* l, Expression* r) :SymbolExpression(l, r) {}
	virtual int interpreter(map<string, int>& var) {
		return left->interpreter(var) + right->interpreter(var);
	}
	virtual ~AddExpression() {
		cout << "~AddExpression()" << endl;
	}
};
class SubExpression :public SymbolExpression {
public:
	SubExpression(Expression* l, Expression *r) :SymbolExpression(l, r) {}
	virtual int interpreter(map<string, int>& var) {
		return left->interpreter(var) - right->interpreter(var);
	}
	virtual ~SubExpression() {
		cout << "~SubExpression" << endl;
	}
};

class Calculator {
private:
	Expression *expression;
public:
	Calculator(const string& expStr) {
		expression = nullptr;
		stack<Expression*> stkExp;

		Expression* left = nullptr;
		Expression* right = nullptr;

		for (unsigned int i = 0; i < expStr.length(); i++) {
			switch (expStr[i]) {
			case '+':
				left = stkExp.top();
				stkExp.pop();
				right = new VarExpression(expStr.substr(++i, 1));
				stkExp.push(new AddExpression(left, right));
				break;

			case '-':
				left = stkExp.top();
				stkExp.pop();
				right = new VarExpression(expStr.substr(++i, 1));
				stkExp.push(new SubExpression(left, right));
				break;

			default:
				stkExp.push(new VarExpression(expStr.substr(i, 1)));
				break;

			}
		}
		if (!stkExp.empty()) {
			expression = stkExp.top();
			stkExp.pop();
		}

	}
	void deltree(Expression* expression) {
		SymbolExpression* branch = dynamic_cast<SymbolExpression*>(expression);
		if (branch == nullptr)
			delete expression;
		else {
			deltree(branch->getLeft());
			deltree(branch->getRight());
			delete expression;
		}
	}
	~Calculator() {
		deltree(expression);
		expression = nullptr;
	}

	int run(map<string, int>& var) {
		return (expression == nullptr) ? 0 : expression->interpreter(var);
	}
};


int main(void) {
	string expStr = "a+b-c";
	map<string, int> var;
	var["a"] = 100;
	var["b"] = 20;
	var["c"] = 40;
	Calculator cal(expStr);
	int ret = cal.run(var);
	cout << ret << endl;

	return 0;
}

2. 分析解释器模式

如果需要增加新的语法,只需要增加Expression派生类就可以了;
如果有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树的时候,可以使用解释器模式;
解释器的缺点:当语言有很多的语法规则的时候,Expression就可能会有很多的派生类,非常难以管理与维护。此时不建议使用解释器模式;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值