C++ 设计模式 解析器

以下内容均来自GeekBand极客班C++ 设计模式课程(李建忠老师主讲)

Interpreter

在特定领域中,某些变化虽然频繁,但可以抽象为某种规则。这时候,结合特定领域,将问题抽象为语法规则,从而给出在该领域下的一般性解决方案。

典型模式:

Interpreter

 

动机(Motivation)

在软件构建过程中,如果某一特定领域的问题比较复杂,类似的结构不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化。

在这种情况下,将特定领域的问题表达为某种语法规则下的句子,然后构建一个解释器来解释这样的句子,从而达到解决问题的目的。

C++ 设计模式 解析器_第1张图片

示例

我们需要先构建一个有规律的复杂问题:

构建一个能够识别表达式的智能计算器:

string expStr = "a+b-c+d";

正如这个表达式所述,可以千变万化,但是四则运算规律是不会改变的

 C++ 设计模式 解析器_第2张图片

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

假定现在有一个基类:

//基类:总的表达式
class Expression{
public:
    virtual int interpreter(map var) = 0;
    virtual ~Expression(){}
};

下面书写一个变量表达式,从图中可以看出,是一个叶子结点:

//变量表达式
class VarExpression : public Expression{
    char key;
public:
    VarExpression(const char & key){
        this->key = key;
    }
    int interpreter(map var){
        return var[key];
    }
};

下面书写一个符号表达式,从图中可以看出,该结点为根结点:

//符号表达式
class SymbplExpression : public Expression{
    //运算符左右两个参数
protected:
    Expression * left;
    Expression * right;
public:
    SymbplExpression(Expression * _left,Expression * _right):
    left(_left),right(_right){

    }

};

具体运算规则的实现如下: 

//实现加法操作
class AddExpression : public SymbplExpression{
public:
    AddExpression(Expression * _left,Expression * _right)
        :SymbplExpression(_left,_right){

    }
    //具体进行执行
    int interpreter(map var) override {
        //返回左子树和右子树的内容,让后将其相加,并返回结果
        return left->interpreter(var) + right->interpreter(var);
    }

};
//实现减法操作
class SubExpression : public SymbplExpression{
public:
    SubExpression(Expression * _left,Expression * _right)
        :SymbplExpression(_left,_right){

    }
    //具体进行执行
    int interpreter(map var) override {
        //返回左子树和右子树的内容,让后将其相减,并返回结果
        return left->interpreter(var) - right->interpreter(var);
    }
};

下面我们要构建一颗树,书写一个analyse函数,

Expression * analyse(string expStr){
    stack expStack;
    Expression * left = nullptr;
    Expression  * right = nullptr;
    for(int i = 0;i

之后进入主函数:

void main(){
    string expStr = "a+b-c+d";//正如这个表达式所述,可以千变万化,但是其中的运算法则是不会发生变化的
    map var;
    //根据情况,将表达式中的变量赋值为实际的数值
    var.insert(make_pair('a',5));
    var.insert(make_pair('b',2));
    var.insert(make_pair('c',1));
    var.insert(make_pair('d',6));

    Expression * expression = analyse(expStr);//针对表达式进行解析,获得根结点

    int result = expression->interpreter(var);
    cout<

interpreter函数不断的递归,对表达式进行具体的运算

要点总结

Interpreter模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的结构不断重复出现,并且不容易抽象为语法规则的问题”才适合使用Interpreter模式。

使用Interpreter模式来表示文法规则,从而可以使用面向对象技巧来方便的“扩展”文法。

Interpreter模式比较适合简单的文法表示,对于复杂的文法表示,Interpreter模式会产生比较大的类层次结构,需要求助于语法分析生成器这样的标准工具

 

你可能感兴趣的:(重构)