解释器模式和策略模式有什么区别?
简化版
策略模式封装可替换算法,调用方从一组算法中选择一个执行;解释器模式定义语法规则并解释表达式,通常会把多个表达式组合成语法树。策略解决算法替换,解释器解决表达式语义解释。
详细版
策略模式:
- 关注算法族。
- 通常一次选择一个策略。
- 输入输出相对固定。
- 不强调语法结构。
解释器模式:
- 关注语言或表达式语法。
- 表达式可以递归组合。
- 需要 Context。
- 常构建表达式树。
例子:
- 多种折扣算法:策略模式。
- 用户配置
amount > 100 AND isVip:解释器模式。
两者都能封装变化,但变化点不同。
完整版教学
一、策略模式的变化点
策略模式的变化点是算法。比如同一个订单金额,可以用普通折扣、会员折扣、活动折扣计算。
调用方选一个策略执行即可,不需要语法树。
二、解释器模式的变化点
解释器模式的变化点是表达式结构。表达式可能由变量、常量、比较、逻辑组合而成。
它不是在一堆算法中选一个,而是在解释一段符合语法的规则。
三、为什么容易混淆
简单规则判断也可以用策略写。比如“是否会员”可以是一个策略。但当规则需要组合、嵌套、由字符串配置驱动时,解释器模式更合适。
策略更像一组平铺算法,解释器更像一棵表达式树。
四、常见误区与工程判断
如果需求是“根据类型选择一种处理逻辑”,优先考虑策略。如果需求是“用户可以配置规则表达式,系统解释执行”,再考虑解释器。
工程中不要为了一个 if else 写解释器模式。模式复杂度要匹配业务复杂度。
五、策略解决算法替换,解释器解决语法执行
策略模式和解释器模式都可能表现为“传入一个对象执行逻辑”,但抽象层次不同。策略模式通常是多个互斥算法之间选择一个,比如选择满减、折扣、会员价;解释器模式是把一条规则拆成表达式树,多个表达式节点组合后共同解释。
如果需求是“同一个业务点有几套固定算法”,策略更合适;如果需求是“用户或配置可以组合出很多规则表达式”,解释器更合适。策略的变化单位是整套算法,解释器的变化单位是语法节点和表达式组合。
面试时可以用支付计价和权限规则对比:支付计价选择不同策略即可;权限规则可能是 A && (B || !C),需要表达式树和上下文求值,这就是解释器更擅长的地方。
如果面试官问“策略能不能表达复杂规则”,答案是可以,但会变笨重。每一种组合都写成一个策略类,会导致策略数量爆炸;解释器则把组合能力交给表达式树,用少量节点类型组合出大量规则。这是二者在扩展方式上的根本差异。
从维护方式看,策略类通常由开发者新增和发布;解释器规则往往可以通过配置组合出来。前者变化更受控,后者灵活性更高但也更需要校验、权限和可观测性。这个差别在工程落地时非常重要。
六、用工程约束检验答案
策略是在若干完整算法中选一个,例如 3 种计价策略;解释器则组合语法节点,例如 vip AND amount > 100 由变量、比较、AND 构成树。前者选择算法,后者根据文法构造并执行表达式。
| 检查项 | 核心判断 | 工程含义 |
|---|---|---|
| Strategy | 算法族整体替换 | Context 持有一个策略 |
| Interpreter | 语法单元递归组合 | Client/Parser 构造 AST |
| 变化粒度 | 一整套算法 | 终结符与非终结符规则 |
把关键关系压缩成一条可复述的路径:
pricingStrategy.calculate(order)
对比
And(IsVip, GreaterThan(amount,100))
.interpret(context)
策略对象通常独立完成算法,解释器节点通常只完成一条文法规则并依赖子节点组合。
落地前可以再按下面 3 步复核:
- 先说明“Strategy”的核心机制:算法族整体替换;再交代边界:Context 持有一个策略。
- 接着分析“Interpreter”:语法单元递归组合;不能遗漏对应代价或结果:Client/Parser 构造 AST。
- 最后用“变化粒度”检查方案:一整套算法;验收时确认终结符与非终结符规则。
这三项构成完整判断链:先讲清Strategy,再说明Interpreter,最后用变化粒度检验实现是否越界。
面试中若能给出违反“终结符与非终结符规则”的反例,再说明修正办法,答案就从模式定义落到了可验证的工程决策。
七、常见误区与追问
- 误区:只看到“Strategy”就认为方案成立。 必须同时说明核心机制“算法族整体替换”和工程边界“Context 持有一个策略”。
- 误区:把“Interpreter”当成无条件结论。 只有在“语法单元递归组合”成立时,才能据此讨论“Client/Parser 构造 AST”。
- 追问:表达式求值算法可做策略吗? 可以把不同求值后端做成策略,但 AST 语法结构仍属于解释器问题。
- 追问:运行时选择节点算策略吗? 仅仅运行时选择不够,关键看选择的是完整算法还是组合语法。
- 追问:二者都符合开闭原则吗? 都只对预期变化轴友好,新增语法可能仍需改 Parser。
- 追问:策略会递归吗? 可以递归,但递归不是区分点,文法组合才是。
- 追问:最短区分句是什么? 策略替换算法,解释器表示并执行语言。
八、加强记忆
记忆时抓住这条主线:策略模式封装算法选择;解释器模式解释语法表达式;策略通常平铺,解释器通常成树;是否存在可组合语法是关键区别。面试回答先给出模式意图,再用调用链或数据流说明角色协作,最后主动交代适用边界与工程代价。