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就可能会有很多的派生类,非常难以管理与维护。此时不建议使用解释器模式;