【设计模式详解】探秘解释器模式,掌握解释器模式的艺术及其神奇力量【C++代码实现示例】

2024-01-03 12:24:49

其他模式的详解:

【设计模式】桥接模式详解,如何优雅地处理不同维度的系统变化? 有原理、示例、场景、优缺点及常见面试题和答案-CSDN博客

【设计模式详解】外观模式:简化复杂系统接口的大门,一键式接入,无忧使用 C++代码详解实现-CSDN博客?

【设计模式】功能无限,结构不变:探秘装饰器模式的神奇魔力,揭秘装饰器模式的设计精髓-CSDN博客

【设计模式】适配器模式 告别接口难题,让你的代码更兼容,让你的接口不再孤单,解锁接口兼容新境界,让你的代码变得更灵活!-CSDN博客

前言:

咱们一起来聊聊行为型设计模式的解释器模式。

一、原理及示例代码

解释器模式是一种行为型设计模式,它用于定义语言的文法,并且在运行时解释和执行语言中的表达式。该模式通常包含以下几个角色:

  1. 抽象表达式(Abstract Expression):定义了一个抽象的接口,用于解释和执行特定的语法规则。
  2. 终结符表达式(Terminal Expression):实现了抽象表达式接口,用于表示语言中的终结符(如变量、常量等)。
  3. 非终结符表达式(Non-terminal Expression):实现了抽象表达式接口,用于表示语言中的非终结符,通常由多个终结符或非终结符组成。
  4. 上下文(Context):包含解释器需要的全局信息,对解释器进行初始化和赋值。

下面是一个简单的 C++ 示例代码,演示了如何使用解释器模式来解释和执行简单的数学表达式:

#include <iostream>
#include <map>

// 抽象表达式
class Expression {
public:
    virtual int interpret(std::map<char, int>& context) = 0;
};

// 终结符表达式
class VariableExpression : public Expression {
private:
    char name;
public:
    VariableExpression(char name) : name(name) {}
    int interpret(std::map<char, int>& context) override {
        return context[name];
    }
};

// 非终结符表达式
class AddExpression : public Expression {
private:
    Expression* left;
    Expression* right;
public:
    AddExpression(Expression* left, Expression* right) : left(left), right(right) {}
    int interpret(std::map<char, int>& context) override {
        return left->interpret(context) + right->interpret(context);
    }
};

int main() {
    // 构建解释器需要的上下文
    std::map<char, int> context;
    context['a'] = 5;
    context['b'] = 7;

    // 构建表达式:a + b
    Expression* expression = new AddExpression(new VariableExpression('a'), new VariableExpression('b'));

    // 执行表达式
    int result = expression->interpret(context);
    std::cout << "Result: " << result << std::endl;

    delete expression;
    return 0;
}

在上面的示例中,我们定义了抽象表达式?Expression,终结符表达式?VariableExpression?和非终结符表达式?AddExpression。然后,我们创建了一个上下文?context,并构建了一个简单的数学表达式?a + b。最后,我们执行表达式并输出结果。

二、结构图

解释器模式的结构图如下所示:

  +---------------------+      +---------------------+
  |   AbstractExpression|      |   TerminalExpression|
  +---------------------+      +---------------------+
  |   interpret()       |      |   interpret()       |
  +---------------------+      +---------------------+
              |                        |
              |                        |
              +------------------------+
                           |
                           |
                  +------------------+
                  | NonterminalExpression|
                  +------------------+
                  |   interpret()    |
                  +------------------+

在上面的结构图中,我们可以看到以下几个重要的角色:

  1. AbstractExpression(抽象表达式):定义了一个抽象的接口,包含?interpret?方法,用于解释和执行特定的语法规则。
  2. TerminalExpression(终结符表达式):实现了抽象表达式接口,用于表示语言中的终结符,通常包含?interpret?方法来执行具体的解释。
  3. NonterminalExpression(非终结符表达式):同样实现了抽象表达式接口,用于表示语言中的非终结符,通常由多个终结符或非终结符组成,也包含?interpret?方法来执行具体的解释。

这些角色共同协作,使得解释器模式可以解释和执行特定语言的表达式。

三、使用场景

解释器模式通常在以下情况下使用:

  1. 当有一个简单的语法规则,并且需要解释和执行这个语法规则时,可以使用解释器模式。例如,数学表达式、逻辑表达式等都可以使用解释器模式来解释和执行。

  2. 当需要构建一个可以灵活扩展的语言解释器时,可以使用解释器模式。通过定义抽象表达式和具体的终结符表达式、非终结符表达式,可以轻松地扩展语言的语法规则。

下面分别给出这两种情况的C++示例代码:

场景一:数学表达式解释器

#include <iostream>
#include <map>

// 抽象表达式
class Expression {
public:
    virtual int interpret(std::map<char, int>& context) = 0;
};

// 终结符表达式
class VariableExpression : public Expression {
private:
    char name;
public:
    VariableExpression(char name) : name(name) {}
    int interpret(std::map<char, int>& context) override {
        return context[name];
    }
};

// 非终结符表达式
class AddExpression : public Expression {
private:
    Expression* left;
    Expression* right;
public:
    AddExpression(Expression* left, Expression* right) : left(left), right(right) {}
    int interpret(std::map<char, int>& context) override {
        return left->interpret(context) + right->interpret(context);
    }
};

int main() {
    // 构建解释器需要的上下文
    std::map<char, int> context;
    context['a'] = 5;
    context['b'] = 7;

    // 构建表达式:a + b
    Expression* expression = new AddExpression(new VariableExpression('a'), new VariableExpression('b'));

    // 执行表达式
    int result = expression->interpret(context);
    std::cout << "Result: " << result << std::endl;

    delete expression;
    return 0;
}

场景二:自定义语言解释器

#include <iostream>
#include <map>
#include <string>

// 抽象表达式
class Expression {
public:
    virtual int interpret(std::map<std::string, int>& context) = 0;
};

// 终结符表达式
class NumberExpression : public Expression {
private:
    int value;
public:
    NumberExpression(int value) : value(value) {}
    int interpret(std::map<std::string, int>& context) override {
        return value;
    }
};

// 非终结符表达式
class VariableExpression : public Expression {
private:
    std::string name;
public:
    VariableExpression(const std::string& name) : name(name) {}
    int interpret(std::map<std::string, int>& context) override {
        return context[name];
    }
};

int main() {
    // 构建解释器需要的上下文
    std::map<std::string, int> context;
    context["x"] = 5;
    context["y"] = 7;

    // 构建表达式:2 * x + y
    Expression* expression = new AddExpression(
        new MultiplyExpression(new NumberExpression(2), new VariableExpression("x")),
        new VariableExpression("y")
    );

    // 执行表达式
    int result = expression->interpret(context);
    std::cout << "Result: " << result << std::endl;

    delete expression;
    return 0;
}

在这两个示例中,我们分别展示了数学表达式解释器和自定义语言解释器的使用,演示了如何使用解释器模式来解释和执行特定的语法规则。

四、优缺点

解释器模式(Interpreter Pattern)的优点和缺点如下:

优点:

  1. 易于扩展:可以通过增加新的表达式类来扩展语言的语法规则,而不需要修改现有的代码。
  2. 易于实现语法解释:对于简单的语法规则,使用解释器模式可以很容易地实现语法解释和执行。
  3. 易于维护:将语法规则的解释功能封装在表达式类中,使得代码易于维护和理解。

缺点:

  1. 可能导致类膨胀:随着语法规则的复杂性增加,可能需要创建大量的表达式类,导致类的数量膨胀,使得系统变得复杂。
  2. 可能降低性能:解释器模式通常需要对语法规则进行解释和执行,可能会导致性能上的一些损失,特别是在处理复杂语法规则时。

总的来说,解释器模式适合用于处理简单的语法规则的解释和执行,但在处理复杂的语法规则时可能会导致类膨胀和性能损失。在选择是否使用解释器模式时,需要根据具体的场景和需求进行权衡。

------------------------------------------分界线-------------------------------------------

? ? ?5 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ?
? ? ? ? ? ? ? +---+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
? ? ? ? ? ? ? | ? | 3 ? ? ? ? ? ? ? ? ? ? ? 3 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |---|
? ? ? ? | ? ? ?| ? | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | ? |
? ? ? ? | ? ? ?| ? +---+ ? ? ? ? ? ? ? ? ? ----- ? ? ? ? ? ? ? ? ?+ ---+ ? ? ? ? ? ? ? ? ? ? ? | ? |
? ? ? ? | ? ? ?| + ? ? ?| ? ? ? | ? ? ? ? ? ?| ? | ? ? ? ? ? ? ? ? ?+ ? ? |----|3 ? ? ? ? ? ? ?| ? |
? + ? ? | ? ?2 | + ? ? ?| ? ? ? | ? ? ? ? ?2 | ? | ? ? 2 ? ? ? ? ? ?+ ? ? | ? ?| ? ? ? ? ? ? ? | ? |
? + ? ? | ? ? ?| + ? ? ?| ? ? ? | ? ? ? ? ? ?| ? | ? ? ? ? ? ? ? ? ?+ ? ? | ? ?| ? ? ? ? ? ? ? | ? |
? + ? ? | ?+---+ + ? ? ?| ? ? ? | ? ? ? ?----+ ? | ? +---+ ? ? ? ? ?+ ? ? | ? ?| ? ? ? ? ? ? ? | ? |
? + ? ? ? | ? ? + ? ? ?| ? ? ? | ? ? ? ?| ? ? ? | ? | ? | ? ? ? ? ?+ ? ? | ? ?| ? ?++++++| ? ?| ? |
? + ? ? 1 | ? ? + ? ? ?| 1 ? ? | ? ? ?1 | ? ? ? | 1 | ? | 1 ? ? ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? + ? ? ? | ? ? + ? ? ?| ? ? ? | ? ? ? ?| ? ? ? | ? | ? | ? ? ? ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? + ? +---+ ? ? + ? ? ?+---+ ? | ? ?+---+ ? ? ? +---+ ? +---+ ? ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? + ? | ? ? ? ? + ? ? ? ? ?| ? | ? ?| ? ? ? ? ? ? ? ? ? ? ? | ? ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? + 0 | ? ? ? ? + ? ? ? ? ?| 0 | ?0 | ? ? ? ? ? ? ? ? ? ? ? | 0 ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? + ? | ? ? ? ? + ? ? ? ? ?| ? | ? ?| ? ? ? ? ? ? ? ? ? ? ? | ? ? ?+ ? ? | ? ?| ? ?| ? ? | ? ?| ? |
? +---+ ? ? ? ? + ? ? ? ? ?+-------+ ? ? ? ? ? ? ? ? ? ? ? +---+ ?+ ?+--- | ? ?|+ ? | ? ? |++ | ? |+
?? ??? ??? ??? ?+?? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ??? ? ?
? ? 0 ? 1 ? 2 ? 3 ? 4 ? 5 ? 6 ? 7 ? 8 ? 9 ?10 ?11 ?12 ?13 ?14 ? 15 ?16 ?17 ?18 19 ?20 ?21
?

文章来源:https://blog.csdn.net/mars1199/article/details/135352071
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。