十分钟学会一个设计模式---行为模式---解释器模式

97 阅读1分钟

一、介绍

解释器模式在实际的系统开发中使用的非常少,因为它会引起效率、性能以及维护等问题,一般在大中型的框架型项目能够找到它的身影,比如一些数据分析工具、报表设计工具、科学计算工具等等,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具

image.png

二、举例

整个过程可以用树状结构进行表示,比如,a+b = temp,之后向上传递,其二者的和temp和c做减法,一次类推

image.png

三、代码

class Expression {
public:
    virtual int interpreter(unordered_map<char, int> var) = 0;
};

// 变量表达式,终止表达式,是一个叶子结点
class VarExpression : public Expression {
    char key;
public:
    VarExpression(const char &key) {
        this->key = key;
    }

    int interpreter(unordered_map<char, int> var) override {
        return var[key];
    }
};

// 符号表达式,非终止表达式,非叶子节点
class SymbolExpression : public Expression {
    // 运算符
protected:
    Expression *left;
    Expression *right;
public:
    SymbolExpression(Expression *left, Expression *right) :
            left(left), right(right) {}
};

// 加法运算
class AddExpression : public SymbolExpression {
public:
    AddExpression(Expression *left, Expression *right) :
            SymbolExpression(left, right) {}

    int interpreter(unordered_map<char, int> var) override {
        return left->interpreter(var) + right->interpreter(var);
    }
};

// 减法运算
class SubExpression : public SymbolExpression {
public:
    SubExpression(Expression *left, Expression *right) :
            SymbolExpression(left, right) {}

    int interpreter(unordered_map<char, int> var) override {
        return left->interpreter(var) - right->interpreter(var);
    }
};

// 构建树
Expression *analyse(string expStr) {
    stack<Expression *> expStack;
    Expression *left = nullptr;
    Expression *right = nullptr;
    for (int i = 0; i < expStr.size(); i++) {
        switch (expStr[i]) {
            case '+':
                // 加法运算
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new AddExpression(left, right));
                break;
            case '-':
                // 减法运算
                left = expStack.top();
                right = new VarExpression(expStr[++i]);
                expStack.push(new SubExpression(left, right));
                break;
            default:
                // 终结表达式
                expStack.push(new VarExpression(expStr[i]));
        }
    }
    Expression *expression = expStack.top();
    return expression;
}

void release(Expression *expression) {
    // 释放表达式树的节点内存...
}

int main() {
    //正如这个表达式所述,可以千变万化,但是其中的运算法则是不会发生变化的
    string expStr = "a+b-c+d";
    unordered_map<char, int> var;

    //根据情况,将表达式中的变量赋值为实际的数值
    var.insert({'a', 5});
    var.insert({'b', 2});
    var.insert({'c', 1});
    var.insert({'d', 6});
    //针对表达式进行解析,获得根结点
    Expression *expression = analyse(expStr);
//    interpreter函数不断的递归,对表达式进行具体的运算
    int result = expression->interpreter(var);
    cout << result << endl;
    release(expression);
    return 0;
}

四、参考

blog.csdn.net/u014600626/… blog.csdn.net/qq_41605114…