- 浏览: 345120 次
- 性别:
- 来自: 广州
-
文章分类
最新评论
在给定一种语言后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器,客户端可以使用这个解释器来解释这个语言中的句子.这样就可以建造一个解释器,通过解释这些语句达到解决问题的目的.例如依照一个匹配模式搜寻字符串便是一个常见的问题,与其为每一个匹配模式建造一个特定的算法,不如建造一个一般性的算法处理各种常规表达式,当接到一个指定的常规表达式时,系统使用一个解释器解释这个常规表达式,从而对字符串进行区配.现在要介绍的解释器模式将怎么样在有了一个简单的文法后使用模式设计解释这些语句,熟悉了这个模式之后,一个没有接收过形式语言(什么是形式语言)和编译器(看来读编译原理是必须的)的正规训练的设计师也可以自行设计一个简单的解释器!
一:语言,解释器和浏览器
解释器模式只描述解释器是怎么样工作的,并不指明怎么样在运行时创建新的解释器。虽然广义地讲,解释器不一定要有一个浏览器(Parser),但是使用浏览器仍然是最常见的建立解释器的办法.一个浏览器可以从一个文件或命令行读入文字性命令,并创建解释器.
浏览器是一种能够识别文字并将文字按照一定规则进行分解以便进一步处理的对象。浏览器能够识别的字符叫做语言.通常建立的小型计算机语言是与环境无关的语言,也就是遵循一定的方法的文字模式。所谓文法,便是决定怎么样将语言元素组合起来的规则的集合。浏览器便是根据组合规则将字符串分解的.
抽象地讲,语言并不一定是以字符串的形式表达的,在解释器模式里面所提到的语言是指任何解释器能够解释的任何组合。在解释器模式中,需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则:每一个命令对象都有一个解释方法,代表对命令对象的解释.
命令对象的等级结构中的对象的任何排列组合都是一个语言,而浏览器的工作便是将一个文字性语言翻译成为等效的解释器语言,因此解释器往往需要浏览器
二:模式所涉及的角色
(A)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口,这个接口主要是一个interpret()方法,称作解释操作.
(B)终结符表达式(TerminalExpression)角色:这是一个具体角色,实现了抽象表达式角色,文法中的每一个终结符都有一个具体终结表达式与之相对应.
(C)非终结表达式(NonterminalExpression)角色:文法中的每一条规则R=R1R2...Rn都需要一个具体的非终结符表达式类,对每一个R1R2....Rn中的符号都持有一个静态类型为Expression的实例变量,实现解释操作interpret,解释操作以递归方式调用上面所提到的代表R1R2....Rn中各个符号的实例变量
(D)客户端(Client)角色:代表模式的客户端有以下功能:建造一个抽象语法树,调用解释操作interpret
在一般情况下,模式还需要一个环境(Context)角色:提供解释器之外的一些全局信息,比如变量的真实值等.
三:一个示意性的实现
为了说明解释器模式的实现办法,这里给出一个最简单的文法和对应的解释器模式的实现--模拟Java语言中对布尔表达式进行操作和求值.
在这个语言中,终结符是布尔变量,也就是常量true和false,非终结符表达式包含运算符and,or和not等布尔表达式,这个简单的文法如下:
Expression ::=Constant|Variable|Or|And|Not
And ::=Expression 'AND' Expression
Or ::=Expression 'OR' Expression
Not ::=Expression 'Not' Expression
Variable ::=任何标识符
Constant ::='true'|'false'
源码如下:
深入学习请阅读编译原理.
一:语言,解释器和浏览器
解释器模式只描述解释器是怎么样工作的,并不指明怎么样在运行时创建新的解释器。虽然广义地讲,解释器不一定要有一个浏览器(Parser),但是使用浏览器仍然是最常见的建立解释器的办法.一个浏览器可以从一个文件或命令行读入文字性命令,并创建解释器.
浏览器是一种能够识别文字并将文字按照一定规则进行分解以便进一步处理的对象。浏览器能够识别的字符叫做语言.通常建立的小型计算机语言是与环境无关的语言,也就是遵循一定的方法的文字模式。所谓文法,便是决定怎么样将语言元素组合起来的规则的集合。浏览器便是根据组合规则将字符串分解的.
抽象地讲,语言并不一定是以字符串的形式表达的,在解释器模式里面所提到的语言是指任何解释器能够解释的任何组合。在解释器模式中,需要定义一个代表文法的命令类的等级结构,也就是一系列的组合规则:每一个命令对象都有一个解释方法,代表对命令对象的解释.
命令对象的等级结构中的对象的任何排列组合都是一个语言,而浏览器的工作便是将一个文字性语言翻译成为等效的解释器语言,因此解释器往往需要浏览器
二:模式所涉及的角色
(A)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口,这个接口主要是一个interpret()方法,称作解释操作.
(B)终结符表达式(TerminalExpression)角色:这是一个具体角色,实现了抽象表达式角色,文法中的每一个终结符都有一个具体终结表达式与之相对应.
(C)非终结表达式(NonterminalExpression)角色:文法中的每一条规则R=R1R2...Rn都需要一个具体的非终结符表达式类,对每一个R1R2....Rn中的符号都持有一个静态类型为Expression的实例变量,实现解释操作interpret,解释操作以递归方式调用上面所提到的代表R1R2....Rn中各个符号的实例变量
(D)客户端(Client)角色:代表模式的客户端有以下功能:建造一个抽象语法树,调用解释操作interpret
在一般情况下,模式还需要一个环境(Context)角色:提供解释器之外的一些全局信息,比如变量的真实值等.
三:一个示意性的实现
为了说明解释器模式的实现办法,这里给出一个最简单的文法和对应的解释器模式的实现--模拟Java语言中对布尔表达式进行操作和求值.
在这个语言中,终结符是布尔变量,也就是常量true和false,非终结符表达式包含运算符and,or和not等布尔表达式,这个简单的文法如下:
Expression ::=Constant|Variable|Or|And|Not
And ::=Expression 'AND' Expression
Or ::=Expression 'OR' Expression
Not ::=Expression 'Not' Expression
Variable ::=任何标识符
Constant ::='true'|'false'
源码如下:
引用
package cai.milenfan.basic.test;
/**
*这个抽象类代表终结类和非终结类的抽象化
*其中终结类和非终结类来自下面的文法:<br>
* <pre>
* BooleanExp ::=
* BooleanExp AND BooleanExp
* | BooleanExp OR BooleanExp
* | NOT BooleanExp
* | Variable
* | Constant
* Variable ::= ... // a string of printable, non-white space characters
* Contant ::= "true" | "false"
* </pre>
*/
public abstract class Expression {
/**
*以环境为准,本方法解释给定的任何一个表达式
*/
public abstract boolean interpret(Context ctx);
/**
*检验两个表达式在结构上是否相同
*/
public abstract boolean equals(Object o);
/**
*返回表达式的hash code
*/
public abstract int hashCode();
/**
*将表达式转换成字符串
*/
public abstract String toString();
}
/**
*这个抽象类代表终结类和非终结类的抽象化
*其中终结类和非终结类来自下面的文法:<br>
* <pre>
* BooleanExp ::=
* BooleanExp AND BooleanExp
* | BooleanExp OR BooleanExp
* | NOT BooleanExp
* | Variable
* | Constant
* Variable ::= ... // a string of printable, non-white space characters
* Contant ::= "true" | "false"
* </pre>
*/
public abstract class Expression {
/**
*以环境为准,本方法解释给定的任何一个表达式
*/
public abstract boolean interpret(Context ctx);
/**
*检验两个表达式在结构上是否相同
*/
public abstract boolean equals(Object o);
/**
*返回表达式的hash code
*/
public abstract int hashCode();
/**
*将表达式转换成字符串
*/
public abstract String toString();
}
package cai.milenfan.basic.test; public class Constant extends Expression { private boolean value; public Constant(boolean value) { this.value = value; } public boolean interpret(Context ctx) { return value; } public boolean equals(Object o) { if (o != null && o instanceof Constant) { return this.value == ((Constant) o).value; } return false; } public int hashCode() { return (this.toString()).hashCode(); } public String toString() { return new Boolean(value).toString(); } }
package cai.milenfan.basic.test; public class Variable extends Expression { private String name; public Variable(String name) { this.name = name; } public boolean interpret(Context ctx) { return ctx.lookup(this); } public boolean equals(Object o) { if (o != null && o instanceof Variable) { return this.name.equals(((Variable) o).name); } return false; } public int hashCode() { return (this.toString()).hashCode(); } public String toString() { return name; } }
package cai.milenfan.basic.test; public class And extends Expression { private Expression left, right; public And(Expression left, Expression right) { this.left = left; this.right = right; } public boolean interpret(Context ctx) { return left.interpret(ctx) && right.interpret(ctx); } public boolean equals(Object o) { if (o != null && o instanceof And) { return this.left.equals(((And) o).left) && this.right.equals(((And) o).right); } return false; } public int hashCode() { return (this.toString()).hashCode(); } public String toString() { return "(" + left.toString() + " AND " + right.toString() + ")"; } }
package cai.milenfan.basic.test; public class Or extends Expression { private Expression left, right; public Or(Expression left, Expression right) { this.left = left; this.right = right; } public boolean interpret(Context ctx) { return left.interpret(ctx) || right.interpret(ctx); } public boolean equals(Object o) { if (o != null && o instanceof Or) { return this.left.equals(((Or) o).left) && this.right.equals(((Or) o).right); } return false; } public int hashCode() { return (this.toString()).hashCode(); } public String toString() { return "(" + left.toString() + " OR " + right.toString() + ")"; } }
package cai.milenfan.basic.test; public class Not extends Expression { private Expression exp; public Not(Expression exp) { this.exp = exp; } public boolean interpret(Context ctx) { return !exp.interpret(ctx); } public boolean equals(Object o) { if (o != null && o instanceof Not) { return this.exp.equals(((Not) o).exp); } return false; } public int hashCode() { return (this.toString()).hashCode(); } public String toString() { return " (Not " + exp.toString() + ")"; } }
package cai.milenfan.basic.test; import java.util.HashMap; public class Context { private HashMap map = new HashMap(); public void assign(Variable var, boolean value) { map.put(var, new Boolean(value)); } public boolean lookup(Variable var) throws IllegalArgumentException { Boolean value = (Boolean) map.get(var); if (value == null) { throw new IllegalArgumentException(); } return value.booleanValue(); } }
package cai.milenfan.basic.test; import java.awt.Canvas; public class Client { private static Context ctx; private static Expression exp; public static void main(String[] args) { ctx = new Context(); Variable x = new Variable("x");// Variable y = new Variable("y"); Constant c = new Constant(true); ctx.assign(x, false); ctx.assign(y, true); exp = new Or(new And(c, x), new And(y, new Not(x))); System.out.println("x = " + x.interpret(ctx)); System.out.println("y = " + y.interpret(ctx)); System.out.println(exp.toString() + " = " + exp.interpret(ctx)); } }
深入学习请阅读编译原理.
发表评论
-
Mina重连
2014-05-26 21:29 2941import com.sun.swing.internal. ... -
面试经典
2014-05-24 09:29 6621.mysql innodb引擎,什么叫聚集索引,与非聚集索 ... -
一拍网网站系统架构图
2014-03-28 21:24 646一拍网网站系统架构图 -
Window下安装配置nginx
2013-08-12 16:53 831安装:http://www.cnblogs.com/wen ... -
使用线程池的好处
2013-07-18 14:41 1274使用线程池有两个好处: 1.可以创建和销毁线程所带来的系统 ... -
Java ThreadLocal使用浅析
2013-07-18 14:36 500ThreadLocal通过在其内部保存变量的副本,并且各个副本 ... -
MyBatis学习之简单增删改查操作、MyBatis存储过程、MyBatis分页、MyBatis一对一、MyBatis一对多
2013-07-05 13:06 1205http://blog.csdn.net/zhangwei ... -
分享一位网友的架构杂谈
2013-05-20 23:16 927不容类型的网站,并发处理不一样,例如针对sns这种类型的网站 ... -
JSP页面静态化
2013-04-08 09:20 909http://www.java-zone.org/644.ht ... -
Java compile to C++
2013-03-19 14:53 516http://code.google.com/a/eclips ... -
几个TCP Socket的通信框架
2013-03-19 12:26 1021http://www.oschina.net/p/simple ... -
宝贝鱼
2013-03-18 23:54 702http://code.google.com/p/cshbbr ... -
将Java程序注册成系统服务(NT服务)
2013-03-16 16:14 609http://blog.csdn.net/small____f ... -
Java内存回收机制
2013-03-13 15:47 824http://www.iteye.com/blogs/tag/ ... -
支付宝,百付宝集成
2013-03-13 14:01 1006http://help.alipay.com/support/ ... -
SSH+EXTJS项目下载
2013-03-11 23:02 449http://download.csdn.net/tag/Ex ... -
Hibernate中使用Threadlocal创建线程安全的Session
2013-03-04 20:39 614http://blog.sina.com.cn/s/blog_ ... -
Java Socket多线程通信
2012-10-09 09:53 850当Server没接受到一个Client连接请求之后,都把处理流 ... -
Java 多线程的一个例子
2012-10-09 09:48 1035目录: 1 synchronized的 ... -
app引擎
2012-07-10 09:39 0http://sae.sina.com.cn/ htt ...
相关推荐
第十七讲:解释器模式 第十八讲:中介者模式 第十九讲:职责链模式 第二十讲:迭代模式 第二十一讲:模板方法模式 第二十二讲:备忘录模式 第二十三讲:访问者模式 第二十四讲:状态模式 第二十五讲:命令...
无水印、可复制版本 一、原型模式 ...十四、解释器模式 十五、迭代器模式 十六、备忘录模式 十七、中介者模式 十八、状态模式 十九、观察者模式 二十、策略模式 二十一、模板方法模式 二十二、访问者模式
#### 十五、解释器模式(Interpreter) **定义:** 解释器模式是一种行为型设计模式,它定义一个新的语言的文法,并且建立一个解释器来解释该语言中的句子。这里的“语言”是指使用规定格式和语法的代码。 **应用...
12第十二讲代理模式 13第十三讲外观模式 14第十四讲组合模式 15第十五讲桥接模式 16第十六讲适配器模式 17第十七讲解释器模式 18第十八讲中介者模式 19第十九讲职责链模式 20第二十讲迭代模式 21第二十一讲模板方法...
(一)简单工厂模式 2 (二)策略模式 4 策略与工厂结合 6 单一职责原则 6 开放――封闭原则 6 里氏代换原则 7 依赖倒转原则 7 (三)装饰模式 7 ...(二十三)解释器模式 59 (二十四)访问者模式 61
- **解释器**(Interpreter):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 - **迭代器**(Iterator):提供一种方法顺序访问一个聚合对象中各个元素,而又不...
阿拉伯数字由0-9这十个符号组成,而中文数字则有零、一、二、三、四、五、六、七、八、九和十等字符。例如,阿拉伯数字“123”对应的中文数字是“一百二十三”。在转换过程中,我们需要考虑千位分隔符和小数点,这些...
最后,解释器模式在第十九章中被探讨,这是一种特殊的抽象语法树实现,常用于编译器或解释器的构建,它允许我们将语言表达式转化为程序代码执行。 总的来说,刘伟老师的《设计模式》课程是一份全面的学习资料,不仅...
十、解释器模式 解释器模式是一种行为型模式,提供了一种解释语言元素的接口,使得客户端可以使用解释器来解释语言元素。小傅哥博客中提供的示例代码是 Mybatis 框架中的解释器模式应用,包括 SqlSession 和 ...
#### 十五、解释器模式 **定义**: 解释器模式给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 **优点**: - 扩展性好,灵活; - 易于实现简单文法。 **缺点**:...
#### 十、命令模式与解释器模式 - **命令模式**:将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 - **解释器模式**:给定一个语言,定义它...
解释器模式给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。 #### 二十四、亨元模式(Flyweight Pattern) 亨元模式运用共享技术有效地支持大量细粒度的对象。 ...
十一至二十三的模式包括:命令模式(Command)、代理模式(Proxy)、享元模式(Flyweight)、组合模式(Composite)、解释器模式(Interpreter)、迭代器模式(Iterator)、访问者模式(Visitor)、备忘录模式...
本文将重点介绍以下几种设计模式:策略模式、模板模式、观察者模式、迭代器模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式和解释器模式。 ### 一、策略模式 策略模式定义了一系列算法...
解释器模式是一种行为型设计模式,它允许您定义语言的文法,并且建立一个解释器来解释该语言中的句子。 **应用场景:** 当需要解释的语句以一种简单的语言来表达时,可以使用解释器模式。 **优点:** - 可扩展性...
解释器模式给定一个语言,定义它的文法表示,并提供一个解释器,用于解析该语言的实例。 十六、迭代器模式(Iterator) 迭代器模式提供了一种方法来顺序访问聚合对象的元素,而又不暴露其底层表示。 十七、备忘录...
解释器模式是一种行为型设计模式,它包括定义语言的文法,并建立一个解释器来解释这种语言中的句子。 **应用场景:** 可定义的语言;需要改变和扩展解释器;语法比较简单。 #### 十七、迭代器模式 **定义:** 迭代...
十四、解释器模式 解释器模式是一种行为设计模式,允许我们将语言的表达式解析为对象,并执行相应的操作。 十五、迭代器模式 迭代器模式提供一种方法顺序访问聚合对象的元素,而又不暴露其底层表示。 这些设计模式...
二十、代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问。代理模式相当于为对象提供了一个“代言人”,从而控制对原始对象的访问,达到某种目的。 二十一、享元模式 享元模式是一种结构型设计模式,...
解释器模式用于定义语言的语法,并提供解析的方式。C++中,可以使用类来表示文法元素,结合运算符重载实现解析。 十四、迭代器模式 迭代器模式提供一种方法顺序访问聚合对象的元素,而又不暴露其底层表示。C++标准...