设计模式之-解释器模式

设计模式之-解释器模式一 概念定义 给对象造个迷你编译器 解释器模式 Interpreter Pattern 一种 定义语言文法并解释执行 的行为型设计模式 它为语言中的每条语法规则定义一个类 通过组合这些类来表示句子 表达式 并提供解释执行的

大家好,欢迎来到IT知识分享网。

设计模式之-解释器模式

一、【概念定义】—— “给对象造个迷你编译器”

解释器模式(Interpreter Pattern)
一种“
定义语言文法并解释执行”的行为型设计模式,它为语言中的每条语法规则定义一个类,通过组合这些类来表示句子(表达式),并提供解释执行的方法
核心思想:
将语句表示为抽象语法树(AST),每个节点是一个表达式对象;解释时递归遍历树求值
目标:
实现简单语言的解释执行,支持动态扩展语法规则

口诀:
“解释模式像翻译,语法规则变对象;
组合成树递归跑,字符串变行为强;
SQL正则它擅长,小语言里称霸王!”


二、【解决的问题】—— “硬编码解析”的三大灾难

想象你要让套娃执行咒语:

  • 灾难1:巨型解析函数
  • void executeCommand(String command) { if (command.startsWith(“IF”)) { … } // 解析IF else if (command.startsWith(“LOOP”)) { … } // 解析循环 else if (command.contains(“=”)) { … } // 解析赋值 // … 500行if-else,新增语法规则?改到吐血! }
  • 灾难2:无法动态扩展
    → 想支持“WHILE循环”?必须修改核心解析器!
  • 灾难3:违反开闭原则
    → 每新增一个语法,都要动原有代码!

翻译官出手!

定义 Expression 接口,含 interpret(Context) 方法;每个语法规则一个类:IfExpression, EqualsExpression, GlowCommand;咒语 → 构建表达式对象树 → 调用 root.interpret() → 自动递归执行!

新增“WHILE”?只需写 WhileExpression 类!不用改解析器!


三、【适用场景】—— “自定义语言”的四大领域

✅ 你该用解释器模式,如果符合“四语原则”:

场景

描述

举例

自定义简单语言

需要解释执行自定义语法(非通用编程语言)

套娃控制脚本、游戏技能配置、机器人指令

语法规则固定

语法规则相对稳定,可用文法描述

SQL子集、正则表达式、数学公式

频繁执行相同结构

同类表达式多次执行,可缓存语法树

配置文件规则、动态查询条件

需动态扩展语法

运行时可能新增语法规则

插件化脚本引擎、可扩展的规则引擎

警告:

复杂语言(如完整Java)→ 用专业编译器(ANTLR, JavaCC)!高频执行 → 解释器性能低,考虑编译成字节码!


四、【经典案例】—— 翻译官的四大翻译现场

1. 【SQL Where条件解析】—— 把字符串变数据库查询!

WHERE age > 18 AND city = ‘Beijing’
❌ 手动解析:写满if-else判断操作符、括号、AND/OR优先级 → 地狱!
✅ 解释器模式:

GreaterThanExpression, EqualsExpression, AndExpression;构建树:And( GreaterThan(age,18), Equals(city,”Beijing”) );interpret() → 返回true/false过滤数据!
️ 效果:
动态生成查询条件!支持任意组合!

➗ 2. 【数学公式计算器】—— 计算 “3 * (2 + 1)”!

3 * (2 + 1) → 需要处理运算符优先级、括号
✅ 解释器模式经典案例:

NumberExpression, AddExpression, MultiplyExpression;构建树:Multiply( Number(3), Add(Number(2), Number(1)) );interpret() → 递归计算:2+1=3 → 3*3=9!
效果:
支持任意复杂公式!新增“除法”?加个 DivideExpression!

3. 【游戏技能脚本】—— “当HP<30%时自动喝药”!

⚔️ 配置文件:IF player.hp < 30 THEN use_potion()
✅ 解释器模式:

LessThanExpression, UsePotionCommand;构建树 → 每帧调用 root.interpret() → 自动判断喝药!
效果:
策划改脚本不用程序员改代码!

4. 【正则表达式引擎】—— 解析 “a*b” 匹配字符串!

a*b = 0个或多个a + 一个b
✅ 核心思想类似解释器:

StarExpression, CharExpression, SequenceExpression;构建NFA/DFA状态机(本质是特殊语法树);interpret(“aaab”) → 返回true!
效果:
动态构建匹配规则!


️ 五、【结构简述】—— 翻译官的“语法树工厂”

解释器模式四要素:

角色

职责

套娃咒语比喻

AbstractExpression(抽象表达式)

声明解释操作接口

“咒语单词协议” —— 所有单词必须实现 interpret()

TerminalExpression(终结符表达式)

实现文法中的终结符(如常量、变量)

“基础单词” —— ColorExpression, NumberExpression

NonterminalExpression(非终结符表达式)

实现文法规则(如运算符、条件语句),组合其他表达式

“语法结构” —— IfExpression, AndExpression(持有子表达式)

Context(上下文)

存储解释器外的全局信息

“套娃状态库” —— 当前套娃的颜色、大小等

解释流程:

解析器 将咒语 “IF color=red THEN glow” → 构建表达式树;调用 root.interpret(context);IfExpression.interpret() → 先解释条件 EqualsExpression → 再根据结果解释 GlowExpression 或 SingExpression;
关键:递归解释!组合模式!树形结构!


⚠️ 六、【注意事项】—— “翻译官”的三大陷阱

1. 陷阱1:性能瓶颈

复杂语法树递归解释 → 比编译型语言慢10-100倍!
✅ 优化:
缓存语法树编译成字节码(如JVM)、用状态机替代

2. 陷阱2:语法树复杂

嵌套10层的IF语句?语法树深如迷宫!调试困难!
✅ 优化:
提供语法树可视化工具限制语法规则深度

3. 陷阱3:滥用场景

用解释器模式写完整编程语言?→ 过度设计!维护灾难!
✅ 铁律:
只用于简单、领域特定的语言!


️ 七、【实战应用】—— 套娃咒语翻译实战!

java

深色版本

import java.util.*; // 1. 咒语单词协议(AbstractExpression) interface Expression { void interpret(Context context); } // 2. 上下文(存储套娃状态) class Context { private Matryoshka targetDoll; // 当前操作的套娃 private Map<String, Object> variables = new HashMap<>(); // 变量表 public Context(Matryoshka doll) { this.targetDoll = doll; } public void setVariable(String name, Object value) { variables.put(name, value); } public Object getVariable(String name) { return variables.get(name); } public Matryoshka getTargetDoll() { return targetDoll; } } // 3. 套娃基类(被操作对象) class Matryoshka { private String color; private boolean isGlowing = false; private boolean isSinging = false; public Matryoshka(String color) { this.color = color; } public String getColor() { return color; } public void glow() { isGlowing = true; System.out.println("✨ 套娃开始发光!"); } public void sing() { isSinging = true; System.out.println(" 套娃开始唱歌!"); } public void reset() { isGlowing = isSinging = false; } } // 4. 终结符:获取套娃属性(TerminalExpression) class GetColorExpression implements Expression { @Override public void interpret(Context context) { // 将套娃颜色存入上下文变量 "color_value" String color = context.getTargetDoll().getColor(); context.setVariable("color_value", color); System.out.println(" 读取套娃颜色: " + color); } } // 5. 终结符:常量值(TerminalExpression) class ConstantExpression implements Expression { private String value; public ConstantExpression(String value) { this.value = value; } @Override public void interpret(Context context) { context.setVariable("constant_value", value); System.out.println(" 常量值: " + value); } } // 6. 非终结符:等于比较(NonterminalExpression) class EqualsExpression implements Expression { private Expression leftExpr; private Expression rightExpr; public EqualsExpression(Expression left, Expression right) { this.leftExpr = left; this.rightExpr = right; } @Override public void interpret(Context context) { // 先解释左右表达式 leftExpr.interpret(context); rightExpr.interpret(context); // 获取比较值 Object leftVal = context.getVariable("color_value"); // 假设左边是颜色 Object rightVal = context.getVariable("constant_value"); // 右边是常量 boolean result = leftVal.equals(rightVal); context.setVariable("condition_result", result); // 存储比较结果 System.out.println("⚖️ 比较结果: " + leftVal + " == " + rightVal + " → " + result); } } // 7. 非终结符:发光命令(TerminalExpression - 无子节点) class GlowCommand implements Expression { @Override public void interpret(Context context) { System.out.println(" 执行发光命令!"); context.getTargetDoll().glow(); } } // 8. 非终结符:唱歌命令(TerminalExpression) class SingCommand implements Expression { @Override public void interpret(Context context) { System.out.println(" 执行唱歌命令!"); context.getTargetDoll().sing(); } } // 9. 非终结符:IF语句(NonterminalExpression - 核心!) class IfExpression implements Expression { private Expression condition; private Expression thenCommand; private Expression elseCommand; public IfExpression(Expression condition, Expression thenCmd, Expression elseCmd) { this.condition = condition; this.thenCommand = thenCmd; this.elseCommand = elseCmd; } @Override public void interpret(Context context) { System.out.println("\n 解释 IF 语句..."); // 1. 解释条件表达式 condition.interpret(context); Boolean result = (Boolean) context.getVariable("condition_result"); // 2. 根据条件执行分支 if (result) { System.out.println("✅ 条件为真,执行 THEN 分支"); thenCommand.interpret(context); } else { System.out.println("❌ 条件为假,执行 ELSE 分支"); if (elseCommand != null) { elseCommand.interpret(context); } } } } // 10. 翻译官实战(客户端 - 模拟解析器构建语法树) public class InterpreterTranslationAgency { public static void main(String[] args) { System.out.println(" 套娃咒语翻译局启动!"); // 创建红色套娃 Matryoshka redDoll = new Matryoshka("红色"); Context context = new Context(redDoll); System.out.println("\n=== ♂️ 咒语1: IF 颜色=红色 THEN 发光 ELSE 唱歌 ==="); redDoll.reset(); // 手动构建语法树 (模拟解析器工作) Expression getColor = new GetColorExpression(); // 获取颜色 Expression redConstant = new ConstantExpression("红色"); // 常量"红色" Expression condition = new EqualsExpression(getColor, redConstant); // 颜色 == "红色" Expression glowCmd = new GlowCommand(); // 发光命令 Expression singCmd = new SingCommand(); // 唱歌命令 // 构建IF语句树 Expression ifStmt = new IfExpression(condition, glowCmd, singCmd); // 解释执行! ifStmt.interpret(context); System.out.println("\n=== ♂️ 咒语2: IF 颜色=蓝色 THEN 发光 ELSE 唱歌 ==="); Matryoshka blueDoll = new Matryoshka("蓝色"); context = new Context(blueDoll); // 切换上下文 blueDoll.reset(); // 重用之前的表达式树!(只换上下文) ifStmt.interpret(context); // 新增功能:支持“循环”?创建 LoopExpression 类! // —— 不用修改现有任何Expression类! System.out.println("\n 扩展性展示:新增 WHILE 语句?只需创建 WhileExpression 类!"); } }

运行结果:

深色版本
 套娃咒语翻译局启动! === ♂️ 咒语1: IF 颜色=红色 THEN 发光 ELSE 唱歌 === 解释 IF 语句... 读取套娃颜色: 红色 常量值: 红色 ⚖️ 比较结果: 红色 == 红色 → true ✅ 条件为真,执行 THEN 分支 执行发光命令! ✨ 套娃开始发光! === ♂️ 咒语2: IF 颜色=蓝色 THEN 发光 ELSE 唱歌 === 解释 IF 语句... 读取套娃颜色: 蓝色 常量值: 红色 ⚖️ 比较结果: 蓝色 == 红色 → false ❌ 条件为假,执行 ELSE 分支 执行唱歌命令! 套娃开始唱歌! 扩展性展示:新增 WHILE 语句?只需创建 WhileExpression 类!

震撼效果

咒语变对象树:IF color=red THEN glow → 由5个对象组合的树!递归解释:IfExpression 自动调用子表达式,层层求值!完全解耦:新增“唱歌”命令?只需写 SingCommand!不用改IF逻辑!上下文隔离:切换套娃对象 → 同一棵树解释不同结果!
—— 这就是解释器模式的魔力:把字符串魔法变成可执行的对象树!


最后总结:解释器模式 —— 对象界的“迷你编译器”

以前:解析字符串 → 巨型if-else → 难扩展 → 改不动!
✨ 现在:字符串 → 语法树 → 递归解释 → 动态扩展 → 灵活如魔法!
解释器模式就是对象界的“语言翻译官” ——

把人类咒语翻译成对象的行为树!


记忆口诀:

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/187809.html

(0)
上一篇 2025-09-12 09:15
下一篇 2025-09-12 09:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信