行为型 解释器模式

解释器模式(Interpreter Pattern):给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。 (用在SQL解析、符号处理引擎等)

解释器模式:

​ 对输入的内容,构建语法树,按照特定的规则进行解析。

概要分析:

​ 就是对输入的字符进行语法,词法分析,比如数学运算的计算等

使用场景:

​ 比如:处理器,硬盘控制器,浏览器等对输入的信息做不同的解析。

​ 比如:使用指令,控制一套机器人系统

样例Demo:

参考来源:设计模式C++实现(20)——解释器模式_crkres9527-CSDN博客_c++ 解释器模式

感觉这个时解释器的精髓:把复杂的输入解析出想要的结果。 直接拿来用,没有细节分析

//行为型模式:解释器模式
//场景:四则运算

#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <typeinfo>

using namespace std;

//*******************************************抽象表达式类***********************************
class Expression
{
public:
    //解析公式和数值,其中var中的key是公式中的参数,value值是具体的数字
    //如a = 100; b = 20; c = 40
    virtual int interpreter(map<string, int>& var) = 0;
    virtual ~Expression(){};
};


//变量解析器(终结符表达式)
class VarExpression : public Expression
{
    string key;
public:
    VarExpression(string key)
    {
        this->key = key;
    }

    //从map中取出变量的值
    int interpreter(map<string, int>& var)
    {
        return var[key];
    }

    ~VarExpression()
    {
        cout << "~VarExpression()" << endl;
    }
};
//**********抽象运算符号解析器***********************
//抽象运算符号解析器
class SymbolExpression : public Expression
{
protected:
    Expression* left;
    Expression* right;
public:
    SymbolExpression(Expression* left, Expression* right)
    {
        this -> left = left;
        this -> right = right;
    }

    Expression* getLeft()
    {
        return left;
    }
    Expression* getRight()
    {
        return right;
    }
};

//加法解析器
class AddExpression : public SymbolExpression
{
public:
    AddExpression(Expression* left, Expression* right): SymbolExpression(left,right)
    {
    }

    //把左右两个表达式运算的结果加起来
    int interpreter(map<string, int>& var)
    {
        return left->interpreter(var) + right ->interpreter(var);
    }
    ~AddExpression()
    {
        cout << "~AddExpression()" << endl;
    }
};

//减法解析器
class SubExpression : public SymbolExpression
{
public:
    SubExpression(Expression* left, Expression* right): SymbolExpression(left,right)
    {
    }

    //把左右两个表达式运算的结果相减
    int interpreter(map<string, int>& var)
    {
        return left->interpreter(var) - right ->interpreter(var);
    }

    ~SubExpression()
    {
        cout << "~SubExpression()" << endl;
    }
};

//*********************************解析器封装类***************************************
//解析器封装类,这个类是根据迪米特法则进行封装,目的是让Client只与直接朋友打交道,相当于Facade
class Calculator
{
private:
    Expression* expression;
public:
    //构造函数传参,并解析表达式,构建语法树
    Calculator(string expStr)
    {
        expression = NULL;

        //栈,用来暂存中间结果
        stack<Expression*> stkExp;

        Expression* left  = NULL;
        Expression* right = NULL;

        /*从左到向分析表达式(如:a+b-c),最终的语法树如下:
         *           -
         *         /   \
         *       +     c
         *     /   \
         *    a     b
        */
        for(unsigned int i = 0; i< expStr.length(); i++)
        {
            switch(expStr[i])
            {
            case '+':  //加法
                //1.先从栈中取出左操作数
                left = stkExp.top();
                stkExp.pop();

                //2.从表达式中取出+号后面的右操作数,并生成终结符解析对象
                right = new VarExpression(expStr.substr(++i,1));

                //3.将左右操作数相加,并把结果放入栈中
                stkExp.push(new AddExpression(left, right));

                break;

            case '-':
                //1.先从栈中取出左操作数
                left = stkExp.top();
                stkExp.pop();

                //2.从表达式中取出+号后面的右操作数,并生成终结符解析对象
                right = new VarExpression(expStr.substr(++i,1));

                //3.将左右操作数相减,并把结果放入栈中
                stkExp.push(new SubExpression(left, right));

                break;

            default:
                //如果是变量(终结符):如a+b+c中的a\b\c,
                //则直接生成对应的变量解析器对象
                stkExp.push(new VarExpression(expStr.substr(i,1)));
            }
        }

        //栈中保存的就是最终语法树的根结点(本例为SuuExpression对象)
        if(!stkExp.empty())
        {
            expression = stkExp.top();
            stkExp.pop();
        }
    }

    void deltree(Expression* expression)
    {
        SymbolExpression* branch = dynamic_cast<SymbolExpression*>(expression);
        //叶子结点
        if (branch == NULL)
        {
            delete expression;
        }
        else  //分支结点
        {
            //左子树
            deltree(branch->getLeft());

            //右子树
            deltree(branch->getRight());

            //结点
            delete expression;
        }
    }

    ~Calculator()
    {
        deltree(expression);
        expression = NULL;
    }

    //开始运算
    int run(map<string, int>& var)
    {
        return (expression == NULL) ? 0 : expression->interpreter(var);
    }
};

int main()
{
    string expStr = "a+b-c"; //为简化处理,这里必须是合法的表达式

    map<string, int> var;   //相当于Interpreter模式中的Context
    var["a"] = 100;
    var["b"] = 20;
    var["c"] = 40;

    Calculator cal(expStr);

    cout <<"运算结果为:" << expStr << " = " << cal.run(var) << endl;
    return 0;
}
/*
运算结果为:a+b-c = 80
~VarExpression()
~VarExpression()
~AddExpression()
~VarExpression()
~SubExpression()
*/

demo2:也是参考,只是简单梳理:

//解释器模式
#include <iostream>
#include <string>
using namespace std;

//只是提供一个解释器的中间类,为解释语句做辅助功能,输入要时特定的格式
class Context
{
	public: //通过此类进行中间变量的存储和运算,得到数据通过此类,修改也是通过此类
		Context(int num){ m_num = num;}
	public:
		void setNum(int num){ m_num = num;}
		int getNum(){ return m_num;}
		void setRes(int res){ m_res = res;}
		int getRes(){ return m_res;}
	private:
		int m_num;
		int m_res;
};

//解释器基类   调用接口的入口而已,子类真正调用入参,根据不同的解释做处理 
//可以定义一个基类 实现多个子类不同的解释功能,如运算符+,-,*,/
class Expression
{
public:
	virtual void interpreter(Context *context) = 0;
};

//可以对输入做不同的解析  这里只做了输出
class PlusExpression : public Expression
{
public:
	virtual void interpreter(Context *context)
	{
		int num = context->getNum();
		num++;
		context->setNum(num);
		context->setRes(num);
	}
};

//可以对输入做不同的解析  这里只做了输出
class MinusExpression : public Expression
{
public:
	virtual void interpreter(Context *context)
	{
		int num = context->getNum();
		num--;
		context->setNum(num);
		context->setRes(num);
	}
};

int main()
{  
	//通过一个中间类进行数据的存储转化和设置
	Context *explain = new Context(10);//设置要解释的内容
	Expression *e1 = new PlusExpression;//设置解释器
	e1->interpreter(explain);//调用解释器内的解释函数
	cout << "PlusExpression:" << explain->getRes() << endl;//得到数据结果

	Expression *e2 = new MinusExpression;
	e2->interpreter(explain);
	cout << "MinusExpression:" << explain->getRes() << endl;

	delete explain;
	delete e2;
	delete e1;
	// system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/yun6853992/article/details/119132774