行为型 解释器模式

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 行为型 解释器模式

解释器模式(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;
}
目录
相关文章
|
设计模式 移动开发 数据库
行为型设计模式10-解释器模式
行为型设计模式10-解释器模式
104 1
|
5天前
|
SQL 设计模式 C#
解释器模式
解释器模式是一种行为型设计模式,用于定义语言的文法表示并提供解释器处理语句或表达式。它将语法规则与解释逻辑分离,便于扩展和维护。适用于简单的语法规则、固定文法结构及重复使用的语法解释场景,如数学表达式求值、SQL解析和简单脚本语言。优点包括易于扩展新规则和分离语法逻辑,但复杂文法会导致类数量激增,维护困难。
20 2
|
3月前
|
设计模式 存储 缓存
Java设计模式 - 解释器模式(24)
Java设计模式 - 解释器模式(24)
|
7月前
|
设计模式
【设计模式】解释器模式
【设计模式】解释器模式
|
7月前
|
设计模式 监控 Java
聊聊Java设计模式-解释器模式
解释器模式(Interpreter Design Pattern)指给定一个“语言”,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。这里所指的“语言”是指使用规定格式和语法的代码。
88 4
聊聊Java设计模式-解释器模式
|
7月前
|
设计模式 存储 前端开发
【设计模式】之解释器模式
解释器模式是一种用于解释特定语言或规则的表达式的行为设计模式。在前端开发中,解释器模式可以用于处理复杂的逻辑或规则,并将其转化为可执行的代码。它具有灵活性和可扩展性的优点,但也存在复杂性和性能问题的缺点。通过合理地应用解释器模式,可以提高代码的可读性和可维护性,实现更灵活和可扩展的功能。
79 1
|
7月前
|
算法
行为型 访问者模式
行为型 访问者模式
61 0
|
7月前
行为型 模板模式
行为型 模板模式
40 0
|
设计模式 算法 Java
设计模式-行为型模式:解释器模式
设计模式-行为型模式:解释器模式
|
设计模式 JavaScript 编译器
我学会了,解释器模式
解释器模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
94 0
我学会了,解释器模式