文章目录
✒️四则运算问题
通过解释器模式来实现四则运算,如计算 a+b-c 的值,具体要求
- 先输入表达式的形式,比如 a+b+c-d+e, 要求表达式的字母不能重复
- 在分别输入 a ,b, c, d, e 的值
- 最后求出结果:如图
✒️传统方案解决四则运算问题分析
- 编写一个方法,接收表达式的形式,然后根据用户输入的数值进行解析,得到结果
- 问题分析:如果加入新的运算符,比如
* /
( 等等,不利于扩展,另外让一个方法来解析会造成程序结构混乱, 不够清晰. - 解决方案:可以考虑使用解释器模式, 即: 表达式 -> 解释器(可以有多种) -> 结果
✒️解释器模式基本介绍
- 在编译原理中,一个算术表达式通过词法分析器形成词法单元,而后这些词法单元再通过语法分析器构建语法分析树,最终形成一颗抽象的语法分析树。这里的词法分析器和语法分析器都可以看做是解释器
- 解释器模式(Interpreter Pattern):是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器, 使用该解释器来解释语言中的句子(表达式)
- 应用场景
- 应用可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
- 一些重复出现的问题可以用一种简单的语言来表达
- 一个简单语法需要解释的场景
- 这样的例子还有,比如编译器、运算表达式计算、正则表达式、机器人等
✒️解释器模式的原理类图
✒️对原理类图的说明-即(解释器模式的角色及职责)
- Context: 是环境角色,含有解释器之外的全局信息.
- AbstractExpression: 抽象表达式, 声明一个抽象的解释操作,这个方法为抽象语法树中所有的节点所共享
- TerminalExpression: 为终结符表达式, 实现与文法中的终结符相关的解释操作
- NonTermialExpression: 为非终结符表达式,为文法中的非终结符实现解释操作.
- 说明: 输入 Context he TerminalExpression 信息通过 Client 输入即可
✒️解释器模式来实现四则
-
应用实例要求
通过解释器模式来实现四则运算, 如计算 a+b-c 的值 -
思路分析和图解(类图)
Expression类
VarExpression类,继承Expression类
SymbolExpression类,继承Expression类
AddExpression类,继承SymbolExpression类
SubExpression类,继承SymbolExpression类
Calculator类,可以理解成一个工具类,加不加都无所谓,不影响该模式的结构
Client类,客户端类
运行结果
✒️debug看原理
我们主要看设计模式的运行方式,程序的代码我们就没有必要深究了
通过我们的方法接收到了表达式和对应的值
我们进入Calculator()构造方法
创建了一个栈
这里根据字符是+
我们调用了AddExpression的构造方法,将VarExpression的实例传入到构造方法中去
-
则是SubExpression的构造函数
遍历完之后我们的表达式就被解析成了这样
然后调用run方法
走的是SubExpression的interpreter方法
然后调用AddExpression的interpreter方法,就是计算a+b的结果,从右开始遍历
到AddExpression的interpreter方法之后,走的是VarExpression的interpreter方法
返回a对应的值
右节点则返回20
SubExpression左节点得到值:30
右节点是VarExpression解释器,会返回对应的值
得到25
计算完成,得到结果:5
✒️解释器模式在Spring 框架应用的源码剖析
- Spring 框架中 SpelExpressionParser 就使用到解释器模式
- 代码分析+Debug 源码
SpelExpressionParser类
调用parseExpression方法
根据参数的不同返回不同的解释器
当前情况返回的是SpelExpression解释器
如果是另外一种情况则返回CompositeStringExpression解释器
✒️Expression接囗表达式接囗
下面有不同的实现类,比如SpelExpression或compositeStringExpression。
使用时候,根据你创建的不同的Parser对象,返回不同的Expression对象
✒️解释器模式的注意事项和细节
- 当有一个语言需要解释执行,可将该语言中的句子表示为一个抽象语法树,就可以考虑使用解释器模式,让程序具有良好的扩展性
- 应用场景:编译器、运算表达式计算、正则表达式、机器人等
- 使用解释器可能带来的问题:解释器模式会引起类膨胀、解释器模式采用递归调用方法,将会导致调试非常复杂、效率可能降低.
资料参考:https://www.bilibili.com/video/BV1G4411c7N4
代码地址:https://gitee.com/WangFuGui-Ma/design-pattern/tree/master/design