• 【C++设计模式之解释器模式:行为型】分析及示例


    简介

    解释器模式(Interpreter Pattern)是一种行为型设计模式,它提供了一种解决问题的方法,通过定义语言的文法规则,解释并执行特定的语言表达式。
    解释器模式通过使用表达式和解释器,将文法规则中的句子逐个解释执行。它将一些复杂的业务逻辑分解为一系列的简单表达式,通过解析和执行这些表达式来实现业务逻辑的处理。

    描述

    解释器模式通常用于处理某种特定领域的语言或规则。它将待解析的句子转换为抽象语法树,并按照语法规则逐个解析节点。每个节点都可以表示一个终结符或非终结符,并提供相应的解释方法。

    原理

    解释器模式的核心原理是将句子解析成为抽象语法树,然后通过遍历和解释节点来执行语义操作。解释器模式通常包含以下角色:

    • 抽象表达式(Abstract Expression):定义了解释器的抽象接口,包含解释方法 interpret()。
    • 终结符表达式(Terminal Expression):表示句子中的终结符(如变量、常量等),实现了解释方法 interpret()。
    • 非终结符表达式(Nonterminal Expression):表示句子中的非终结符(如加法、减法等运算),定义了解释方法 interpret()。

    类图

    在这里插入图片描述

    Context:环境角色(上下文),含有每个解释器所需的一些数据或全局的一些信息。
    AbstractExpression:抽象表达式类,声明了抽象的解释操作,所有解释器类都继承或实现该类。
    TerminalExpression:终结符表达式类,是AbstractExpression的子类,实现了文法中有关终结符相关的解释操作。
    NonTerminalExpression:非终结符表达式,AbstractExpression的子类,该类的功能与终结表达式类相反,文法中所有非终结符由该类进行解释。
    Client:客户端测试类。

    示例

    假设我们需要实现一个简单的数学表达式解析器,可以计算表达式的值。表达式可以包含整数、加法和减法操作。

    在下面的示例中,我们定义了抽象表达式类 Expression 和具体的终结符表达式类 IntegerExpression,以及具体的非终结符表达式类 AddExpression 和 SubtractExpression。程序通过解析句子中的各个表达式,并执行相应的操作。

    #include 
    #include 
    #include 
    
    // 抽象表达式类
    class Expression {
    public:
        virtual int interpret() 0;
    };
    
    // 终结符表达式类
    class IntegerExpression : public Expression {
    private:
        int value;
    
    public:
        IntegerExpression(int value) : value(value) {}
    
        int interpret() {
            return value;
        }
    };
    
    // 非终结符表达式类
    class AddExpression : public Expression {
    private:
        Expression* left;
        Expression* right;
    
    public:
        AddExpression(Expression* left, Expression* right)
            : left(left), right(right) {}
    
     int interpret() {
            return left->interpret() + right->interpret();
        }
    };
    
    class Subtract : public Expression {
    private
    	Expression* left;
        Expression* right;
    
    public:
        SubtractExpression(Expression* left, Expression* right)
            : left(left), right(right) {}
    
        int interpret() {
            return left->interpret() - right->interpret();
        }
    };
    
    // 解析器
    class Parser {
    public:
     static Expression* parse(const std::string& input) {
            std::stack<Expression*> expressionStack;
    
            int pos = 0;
            while (pos < input.size()) {
                if (isdigit(input[pos])) {
                    int value = 0;
                    while (pos < input.size() && isdigit(input[pos])) {
                        value = value * 10 + (input[pos] - 0);
                        pos++;
                    }
                   expressionStack.push(new IntegerExpression(value));
                } else if (input[pos] == '+') {
                    Expression* right = expressionStack.top();
                    expressionStack.pop();
                    Expression* left = expressionStack.top();
                    expressionStack.pop();
    
                    expressionStack.push(new AddExpression(left, right));
                    pos++;
                } else if (input[pos] == '-') {
                    Expression* right = expressionStack.top();
                    expressionStack.pop();
                    Expression* left = expressionStack.top();
                    expressionStack.pop();
    
                    expressionStack.push(new SubtractExpression(left, right));
                    pos++;
                } else {
                    pos++;
                }
            }
    
            return expressionStack.top();
        }
    };
    
    int main() {
        std::string input = "5+2-1";
        Expression* expression = Parser::parse(input);
        int result = expression->interpret();
        std::cout << "Result: " << result << std::endl;
    
        delete expression;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    输出结果

    Result: 6
    
    • 1

    解释

    在上述示例中,使用解释器模式实现了一个简单的数学表达式解析器。程序首先将输入的字符串表达式解析成为抽象语法树,并通过遍历和解释节点来执行计算操作。最后输出计算的结果。

    结论

    解释器模式可以用于处理复杂的业务规则和语言解析。它可以将复杂的业务逻辑分解为一系列的简单表达式进行处理,从而提高代码的可读性和维护性。

    应用场景

    解释器模式适用于以下情况:

    • 当业务逻辑较为复杂,且可以被分解为一系列简单表达式时。
    • 当需要构建一种特定领域的语言或解析器时。
    • 当需要灵活地支持变化的业务规则或语法规则时。
  • 相关阅读:
    MySQL8.0.28安装教程
    React—兄弟组件数据传递
    C# 对RabbitMQ使用
    【JAVA】浅解线程池ThreadPoolExecutor的各个参数
    pytorch深度学习实战lesson7
    禁止methtype联网
    typeScript--[类的多态和抽象类、抽象方法]
    windows bat批处理文件,实现某个软件的重启
    经常遇到的问题
    【外卖项目实战开发一】
  • 原文地址:https://blog.csdn.net/MrHHHHHH/article/details/133660104