- 浏览: 173030 次
- 性别:
- 来自: 杭州
文章分类
最新评论
-
lgh1992314:
String.intern()在全局常量池1.8在native ...
Java 内存模型 -
lgh1992314:
try with resource
Java GC的过程 -
lgh1992314:
JDK8 HotSpot 方法区在MetaSpace
Java 内存模型 -
空城回转:
永洁童心 写道最后的图中,在afterload_1步骤中,op ...
栈帧、局部变量表、操作数栈 -
永洁童心:
最后的图中,在afterload_1步骤中,operand s ...
栈帧、局部变量表、操作数栈
1.定义
给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中句子。
属于行为类模式。
2.解释器模式的使用场景
- 重复发生的问题可以使用解释器模式:比如根据用户输入的公式进行加减乘除四则运算,但是他们输入的公式每次都不同,有时是a+b-c*d,有时是a*b+c-d,等等等等个,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。
- 一个简单语法需要解释的场景:你看看下面给出的例子,非终结表达式,文法规则越多,复杂度越高,而且类间还要进行递归调用。因此解释器模式一般用来解析比较标准的字符集,例如sql语法分析,不过该部分逐渐被专用工具所取代。
在实际开发工作中经常会有客户要求计算公式他们自己制定,我们只要按照他们的公式和提供的数据进行运算就行了,那么这个业务逻辑也就不能写死了。
下面让我们工具加减乘除四则运算的例子来看看何谓解释器模式(四则比较麻烦,例子只写加减操作):
package _21InterpretePattern; import java.util.HashMap; /** * 抽象表达式 */ public abstract class Expression { /** * 解析公式和数值,其中var中的key是公式的参数,value值是具体的数字 * 负责对传递进来的参数和值进行解析和匹配,其中key是表达式a+b+c中的a、b、c,value是运算时取得的值 */ // 如果是终结符表达式,那么此方法将获取参数的值 // 如果是非终结符表达式,那么此方法将进行运算,比如加减 public abstract int interpreter(HashMap<String, Integer> var); }
package _21InterpretePattern; import java.util.HashMap; /** * 变量解析器 * 终结符表达式 */ public class VarExpression extends Expression { private String key; public VarExpression(String key) { this.key = key; } // 从map中取得值 @Override public int interpreter(HashMap<String, Integer> var) { return var.get(key); } }
package _21InterpretePattern; /** * 抽象运算符解析器 * 非终结符表达式 */ public abstract class SymbolExpression extends Expression { // 每个运算符都有左右两个参数进行运算,因此抽象到父类中 protected Expression left; protected Expression right; public SymbolExpression(Expression left, Expression right) { this.left = left; this.right = right; } }
package _21InterpretePattern; import java.util.HashMap; /** * 加法解析器 * interpreter方法处理加法运算 */ public class AddExpression extends SymbolExpression { public AddExpression(Expression left, Expression right) { super(left, right); } // 进行加法运算 @Override public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) + super.right.interpreter(var); } }
package _21InterpretePattern; import java.util.HashMap; /** * 减法解析器 * interpreter方法处理减法运算 */ public class SubExpression extends SymbolExpression { public SubExpression(Expression left, Expression right) { super(left, right); } // 进行减法运算 @Override public int interpreter(HashMap<String, Integer> var) { return super.left.interpreter(var) - super.right.interpreter(var); } }
package _21InterpretePattern; import java.util.HashMap; import java.util.Stack; /** * 对输入的表达式进行解析,并计算 */ public class Context { // 定义表达式,最后拿到是一个运算解析器,比如X+Y格式的,其中X可能又是由A+B的运算解析器组成 // 只有最底层的解析器才是变量解析器,也就是终结符表达式 // 此参数最终得到的肯定是非终结表达式 private Expression expression; /** * 分析用户输入的表达式 */ public void analyse(String expStr) { // 定义一个栈,安排运算的先后顺序 Stack<Expression> stack = new Stack<Expression>(); char[] charArray = expStr.toCharArray(); Expression left = null; Expression right = null; for(int i=0; i<charArray.length; i++) { switch(charArray[i]) { case '+': // 将加法运算加入到栈中 left = stack.pop(); right = new VarExpression(String.valueOf(charArray[++i])); stack.push(new AddExpression(left, right)); break; case '-': // 将减法运算加入到栈中 left = stack.pop(); right = new VarExpression(String.valueOf(charArray[++i])); stack.push(new SubExpression(left, right)); break; default: // 如果不是运算符,那么就是终结表达式 stack.push(new VarExpression(String.valueOf(charArray[i]))); } } // 把最终栈的顶层抛出,它即是最后封装的非终结表达式 this.expression = stack.pop(); } // 将键值对输入给表达式运算 public int run(HashMap<String, Integer> var) { return expression.interpreter(var); } }
package _21InterpretePattern; import java.util.HashMap; /** * 场景类 */ public class Client { /** * @param args */ public static void main(String[] args) { String expStr = "a+b-c+d"; HashMap<String, Integer> var = new HashMap<String, Integer>(); var.put("a", 1); var.put("b", 2); var.put("c", 2); var.put("d", 4); Context context = new Context(); // 先解析运算表达式 context.analyse(expStr); // 进行运算 System.out.println(context.run(var)); } }
3.解释器模式的四个角色
- AbstractExpression抽象解释器:声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpreter()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。
- TerminalExpression终结符表达式:实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。
- NonterminalExpression非终结符表达式:文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
- Context环境角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。
4.解释器模式的优点
解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。
5.解释器模式的缺点
- 解释器模式会引起类的膨胀:每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。
- 解释器模式采用递归调用方法:每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过一层一层的剥茧,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式(只在必要条件下使用),它将导致调试非常复杂。想想看,如果要排查一个错误,我们是不是要一个个断点调试下去,直至最小的语法单元。
- 解释器模式使用了大量的循环和递归:效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。
6.解释器模式的注意事项
尽量不要在重要模块中使用解释器模式,否则维护会是一个很大的问题。在项目中可以使用shell、JRuby、Groovy等脚本语言来代替解释器模式、弥补Java编译型语言的不足。我们在一个银行的分析型项目中就采用了JRuby进行运算处理,避免使用解释器模式的四则运算,效率和性能各方面表现良好。
解释器模式在实际的系统开发中使用的非常少,因为它会引起效率、性能以及维护等问题,一般在大中型的框架型项目中能找到它的身影,如一些数据分析工具、报表设计工具、科学计算工具等,如果你确实遇到“一种特定类型的问题发生的频率足够高”的情况,准备使用解释器模式时,可以考虑一下Expression4J、MESP、Jep
等开源的解析工具包,功能都非常强大,而且非常容易使用,效率也不错,实现大多数的数学运算完全没有问题,自己没有必要重头开始编写解释器。
发表评论
-
设计模式代码-仅供参考
2012-11-26 17:13 822学完设计模式,示例代码保存着,以后看看。 -
23.桥梁模式(Bridge Pattern)
2012-11-26 17:09 18311.定义 将抽象和实现解耦,使得两者可以独立地变化 ... -
22.享元模式(Flyweight Pattern)
2012-11-26 14:55 14221.定义 使用共享对象可有效地支持大量的细粒度的对象。 是 ... -
20.状态模式(State Pattern)
2012-11-22 14:02 13141.定义 当一个对象内在状态改变时,允许其改变行为,这个对象 ... -
19.访问者模式(Visitor Pattern)
2012-11-19 16:28 1943话说有一个银行,有三 ... -
18.备忘录模式(Memento Pattern)
2012-11-16 15:01 1070引子 俗话说:世上难 ... -
17.门面模式(FacadePattern)
2012-11-15 15:23 10471.定义 要求一个子系统 ... -
16.观察者模式(ObserverPattern)
2012-11-14 16:08 15551.定义 定义对象之间一种一对多的依赖关系,使得每当一个对象 ... -
15.组合模式(Composite Pattern)
2012-11-13 17:35 18051.定义 将对象组合成树形结构以表示“部分-整体”的层次结构 ... -
14.迭代器模式(Iterator Pattern)
2012-11-13 14:27 11801.定义 提供一种方法访 ... -
13.适配器模式(Adapter Pattern)
2012-11-12 17:24 13541.定义 将一个类的接口变换成客户端所期待的另一种接口,从而 ... -
12.策略模式(Strategy Pattern)
2012-11-12 13:51 11271.定义 定义一组算法,将每个算法都封装起来,并且使它们之间 ... -
11.装饰模式(Decorator Pattern)
2012-11-08 15:57 10551.定义 动态地给一个对 ... -
10.责任链模式(Chain of Responsibility)
2012-11-07 16:15 10611.定义: 使多个对象都有机会处理请求,从而避免了请求的发送 ... -
9.命令模式(Command Pattern)
2012-11-07 14:45 10101.定义 将一个请求封装 ... -
8.中介者模式(Mediator Pattern)
2012-11-01 15:57 15281.定义: 用一个中介对象封装一系列的对象交互,中介者使个对 ... -
7.原型模式(Prototype Pattern)
2012-11-01 10:54 13361.定义: 用原型实例指定创建对象的种类,并且通过拷贝这些原 ... -
6.代理模式(Proxy Pattern)
2012-10-30 16:09 11351.定义: 为其他对象提供一种代理以控制这个对象的访问。 ... -
5.建造者模式(Builder Pattern)
2012-10-26 17:06 10311.定义: 将一个复杂对象的构建与它的表示分离,使得同样的构 ... -
4.模板方法模式(Template Method Pattern)
2012-10-25 16:33 1166定义: 定义一个操作中的算法的框架,而将一些步骤延迟到 ...
相关推荐
解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者模式(Visitor ...
解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者...
17. 解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者...
解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者...
解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) ...
给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子。
解释器模式(Interpreter Pattern) 迭代器模式(Iterator Pattern) 中介者模式(Mediator Pattern) 备忘录模式(Memento Pattern) 观察者模式(Observer Pattern) 状态模式(State Pattern) 空对象模式...
0.1 设计模式解析(总序)........................... 0.2 设计模式解析后记................................... 0.3 与作者联系.............................................. 1 创建型模式......................
17. 解释器模式(Interpreter Pattern) 18. 中介者模式(Mediator Pattern) 19. 职责链模式(Chain of Responsibility Pattern) 20. 备忘录模式(Memento Pattern) 21. 策略模式(Strategy Pattern) 22. 访问者模式...
AML opcode information for the AML parser and interpreter.
使用Qt C++ 开发的计算器小程序,采用解析器、状态机两种模式, 是个人学习设计模式后的总结,希望有所帮助。
A tiny BASIC interpreter in c good
http://www.programmersheaven.com/zone6/cat700/16060.htm A tiny BASIC interpreter with C++ sourcecode
0.1 设计模式解析(总序)...............2 0.2 设计模式解析后记.......................2 0.3 与作者联系..................................5 1 创建型模式.............................................5 ...
C#面向对象设计模式 (行为型模式) Interpreter 解释器模式 视频讲座下载
We'll start with 0 lines of code and end up with a fully working interpreter for the Monkey* programming language. Step by step. From tokens to output. All code shown and included. Fully tested. ...
2. Using the Python Interpreter 使用 Python 解释器 ................... 2.1. Invoking the Interpreter 调用解释器 ............................ 2.1.1. Argument Passing 参数传递 .............................
设计模式精解-GoF 23 种设计模式解析附 C++实现源码 目 录 0 引言 ............................................................................................................................................
C++设计模式代码资源25_Interpreter_解析器.zip
设计模式精解-GoF 23种设计模式解析附C++实现源码 目 录 0 引言.........................................................................................................................................