【C++设计模式】第十五篇:解释器模式(Interpreter)

注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

自定义语法的解析引擎


1. 模式定义与用途

核心思想

  • 解释器模式:定义一种语言的语法表示,并提供解释器来解析和执行该语言。
  • 关键用途
    1.​领域特定语言(DSL):为特定场景设计专用语法(如数据查询、规则引擎)。
    ​2.动态解析逻辑:允许运行时根据输入表达式调整行为(如动态过滤条件)。

经典场景

  • 数学表达式解析(如计算器)。
  • SQL的WHERE条件解析与执行。
  • 正则表达式引擎。

2. 模式结构解析

UML类图

+---------------------+          +---------------------+  
|   AbstractExpression|          |       Context       |  
+---------------------+          +---------------------+  
| + interpret(c: Context)|        | - variables: map    |  
+---------------------+          +---------------------+  
          ^                                ^  
          |                                |  
+---------------------+    +--------------------------------+  
| TerminalExpression  |    | NonTerminalExpression          |  
+---------------------+    +--------------------------------+  
| + interpret()       |    | + interpret()                  |  
+---------------------+    +--------------------------------+  

角色说明

  1. AbstractExpression:抽象表达式接口,定义interpret()方法。
  2. TerminalExpression:终结符表达式(如变量、常量)。
  3. NonTerminalExpression:非终结符表达式(如运算符、组合逻辑)。
  4. Context:上下文环境,存储变量值或中间结果。

3. 现代C++实现示例

场景:自定义布尔逻辑表达式解析

​步骤1:定义上下文与表达式接口
#include <iostream>  
#include <string>  
#include <unordered_map>  
#include <memory>  

// 上下文:存储变量值  
class Context {  
public:  
    void setVariable(const std::string& var, bool value) {  
        variables_[var] = value;  
    }  

    bool getVariable(const std::string& var) const {  
        auto it = variables_.find(var);  
        return it != variables_.end() ? it->second : false;  
    }  

private:  
    std::unordered_map<std::string, bool> variables_;  
};  

// 抽象表达式接口  
class Expression {  
public:  
    virtual ~Expression() = default;  
    virtual bool interpret(const Context& context) = 0;  
};  
步骤2:实现终结符表达式(变量)​
// 终结符:变量  
class VariableExpression : public Expression {  
public:  
    VariableExpression(const std::string& name) : name_(name) {}  

    bool interpret(const Context& context) override {  
        return context.getVariable(name_);  
    }  

private:  
    std::string name_;  
};  
步骤3:实现非终结符表达式(逻辑运算符)
// 非终结符:逻辑与  
class AndExpression : public Expression {  
public:  
    AndExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)  
        : left_(std::move(left)), right_(std::move(right)) {}  

    bool interpret(const Context& context) override {  
        return left_->interpret(context) && right_->interpret(context);  
    }  

private:  
    std::shared_ptr<Expression> left_, right_;  
};  

// 非终结符:逻辑或  
class OrExpression : public Expression {  
public:  
    OrExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)  
        : left_(std::move(left)), right_(std::move(right)) {}  

    bool interpret(const Context& context) override {  
        return left_->interpret(context) || right_->interpret(context);  
    }  

private:  
    std::shared_ptr<Expression> left_, right_;  
};  

// 非终结符:逻辑非  
class NotExpression : public Expression {  
public:  
    NotExpression(std::shared_ptr<Expression> expr)  
        : expr_(std::move(expr)) {}  

    bool interpret(const Context& context) override {  
        return !expr_->interpret(context);  
    }  

private:  
    std::shared_ptr<Expression> expr_;  
};  
步骤4:客户端代码(解析并执行表达式)
// 构造表达式:(A && B) || !C  
int main() {  
    Context context;  
    context.setVariable("A", true);  
    context.setVariable("B", false);  
    context.setVariable("C", true);  

    auto exprA = std::make_shared<VariableExpression>("A");  
    auto exprB = std::make_shared<VariableExpression>("B");  
    auto exprC = std::make_shared<VariableExpression>("C");  

    auto andExpr = std::make_shared<AndExpression>(exprA, exprB);  
    auto notExpr = std::make_shared<NotExpression>(exprC);  
    auto finalExpr = std::make_shared<OrExpression>(andExpr, notExpr);  

    bool result = finalExpr->interpret(context);  
    std::cout << "表达式结果: " << std::boolalpha << result << "\n";  
    // 输出:表达式结果: false(因为 A&&B=false,!C=false,整体为false)  
}  

4. 应用场景示例

场景1:动态SQL条件过滤

class SQLFilter : public Expression {  
public:  
    SQLFilter(const std::string& condition) {  
        // 解析条件字符串为表达式树(示例简化)  
        // 例如:"age > 25 AND (city = 'NY' OR city = 'SF')"  
    }  

    bool interpret(const Context& context) override {  
        // 转换为实际SQL查询  
        return true;  
    }  
};  

场景2:数学表达式计算器

class NumberExpression : public Expression {  
public:  
    NumberExpression(int value) : value_(value) {}  
    int interpret(const Context&) override { return value_; }  

private:  
    int value_;  
};  

class AddExpression : public Expression {  
public:  
    AddExpression(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right)  
        : left_(left), right_(right) {}  

    int interpret(const Context& context) override {  
        return left_->interpret(context) + right_->interpret(context);  
    }  
};  

5. 优缺点分析

​优点​缺点
灵活扩展语法规则复杂语法导致类数量爆炸(需组合表达式)
易于实现简单DSL性能较低(递归解析开销大)
分离语法定义与解析逻辑难以维护复杂文法(需结合解析器生成器)

6. 调试与优化策略

调试技巧(VS2022)​

1. ​跟踪表达式树解析:
  • 在interpret()方法内设置断点,逐层查看表达式计算过程。
2. 验证上下文变量:
  • 使用 ​内存窗口 检查Context中的变量值是否正确。

性能优化

1. ​预编译表达式树:
class PrecompiledExpression {  
public:  
    PrecompiledExpression(std::shared_ptr<Expression> expr) : expr_(expr) {}  
    bool execute(const Context& context) {  
        return expr_->interpret(context);  
    }  
private:  
    std::shared_ptr<Expression> expr_;  
};  
2. ​缓存重复表达式:
class ExpressionCache {  
public:  
    std::shared_ptr<Expression> parse(const std::string& expr) {  
        if (auto it = cache_.find(expr); it != cache_.end()) {  
            return it->second;  
        }  
        auto parsedExpr = buildExpressionTree(expr);  
        cache_[expr] = parsedExpr;  
        return parsedExpr;  
    }  
private:  
    std::unordered_map<std::string, std::shared_ptr<Expression>> cache_;  
};  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JuicyActiveGilbert

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值