C++ 设计模式《智能任务助手上线,小明用上了解释器》
👨🎓 模式名称:解释器模式(Express)
👦 故事背景:
小明最近上线了一个“智能任务助手”功能:
只要输入类似这样的字符串,就能让平台自动执行任务:
“送奶茶 AND 打扫卫生 OR 帮我跑腿”
但问题来了——怎么解析这种自由组合的命令语句呢?
如果用 if/else 硬编码判断,命令组合一变就要重写代码,小明快被气哭了 😭。
于是他学会了——解释器模式!
✅ 使用解释器模式的解决方案
🧱 抽象表达式类
class Expression {
public:virtual bool interpret(const std::string& context) = 0;virtual ~Expression() {}
};
🧱 终结符表达式(每种服务)
class TerminalExpression : public Expression {std::string keyword;
public:TerminalExpression(const std::string& word) : keyword(word) {}bool interpret(const std::string& context) override {return context.find(keyword) != std::string::npos;}
};
🧱 非终结符表达式(AND / OR)
class OrExpression : public Expression {Expression* expr1;Expression* expr2;
public:OrExpression(Expression* e1, Expression* e2) : expr1(e1), expr2(e2) {}bool interpret(const std::string& context) override {return expr1->interpret(context) || expr2->interpret(context);}~OrExpression() {delete expr1;delete expr2;}
};class AndExpression : public Expression {Expression* expr1;Expression* expr2;
public:AndExpression(Expression* e1, Expression* e2) : expr1(e1), expr2(e2) {}bool interpret(const std::string& context) override {return expr1->interpret(context) && expr2->interpret(context);}~AndExpression() {delete expr1;delete expr2;}
};
🌟 创建命令解释器逻辑
Expression* buildExpression() {// "送奶茶 AND 打扫卫生 OR 跑腿"Expression* milkTea = new TerminalExpression("奶茶");Expression* clean = new TerminalExpression("打扫");Expression* runErrand = new TerminalExpression("跑腿");Expression* andExpr = new AndExpression(milkTea, clean);return new OrExpression(andExpr, runErrand);
}
使用示例
int main() {Expression* expr = buildExpression();std::string input1 = "请帮我送奶茶然后打扫下宿舍";std::string input2 = "跑腿去买点东西";std::string input3 = "只是送奶茶";std::cout << "input1: " << expr->interpret(input1) << "\n"; // truestd::cout << "input2: " << expr->interpret(input2) << "\n"; // truestd::cout << "input3: " << expr->interpret(input3) << "\n"; // falsedelete expr;
}
❌ 不使用解释器模式的写法
bool parseCommand(const std::string& cmd) {if (cmd.find("奶茶") != std::string::npos &&cmd.find("打扫") != std::string::npos) {return true;}if (cmd.find("跑腿") != std::string::npos) {return true;}return false;
}
👎 缺点:
- 每次命令组合变动都要修改逻辑
- 无法复用、组合,命令变复杂就变得极其混乱
- 不符合开闭原则(不能方便地添加新服务)
✅ 优势总结
| 优势 | 描述 |
|---|---|
| 📖 自定义小型语言 | 能将规则/命令表达为结构 |
| 🔄 灵活扩展 | 支持组合(AND/OR)、嵌套等复杂逻辑 |
| ♻️ 复用性高 | 表达式可以灵活重用 |
