interpreter(解释器模式)
一、引子
其实没有什么好的例子引入解释器模式,因为它描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发编译器中;在实际应用中,我们可能很少碰到去构造一个语言的文法的情况。
虽然你几乎用不到这个模式,但是看一看还是能受到一定的启发的。 二、定义与结构
解释器模式的定义如下:定义语言的文法,并且建立一个解释器来解释该语言中的句子。它属于类的行为模式。这里的语言意思是使用规定格式和语法的代码。
在GOF的书中指出:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。而且当文法简单、效率不是关键问题的时候效果最好。
呵呵,这也就是解释器模式应用的环境了。
让我们来看看神秘的解释器模式是由什么来组成的吧。
1) 抽象表达式角色:声明一个抽象的解释操作,这个接口为所有具体表达式角色(抽象语法树中的节点)都要实现的。
什么叫做抽象语法树呢?《Java与模式》中给的解释为:抽象语法树的每一个节点都代表一个语句,而在每个节点上都可以执行解释方法。这个解释方法的执行就代表这个语句被解释。由于每一个语句都代表这个语句被解释。由于每一个语句都代表一个常见的问题的实例,因此每一个节点上的解释操作都代表对一个问题实例的解答。
2) 终结符表达式角色:具体表达式。
a) 实现与文法中的终结符相关联的解释操作
b) 而且句子中的每个终结符需要该类的一个实例与之对应
3) 非终结符表达式角色:具体表达式。
a) 文法中的每条规则R::=R1R2…Rn都需要一个非终结符表带式角色
b) 对于从R1到Rn的每个符号都维护一个抽象表达式角色的实例变量
c) 实现解释操作,解释一般要递归地调用表示从R1到Rn的那些对象的解释操作
4) 上下文(环境)角色:包含解释器之外的一些全局信息。
5) 客户角色:
a) 构建(或者被给定)表示该文法定义的语言中的一个特定的句子的抽象语法树
b) 调用解释操作 放上张解释器结构类图吧,这也是来自于GOF的书中。 呵呵,对每一个角色都给出了详细的职责,而且在类图中给出五个角色之间的关系。这样实现起来也不是很困难了,下面举了一个简单的例子,希望能加深你对解释器模式的理解。 三、举例
来举一个加减乘除的例子吧,实现思路来自于《java与模式》中的例子。每个角色的功能按照上面提到的规范来实现。 [java] view plain copy
//上下文(环境)角色,使用HashMap来存储变量对应的数值 class Context { private Map valueMap = new HashMap(); public void addValue(Variable x , int y) { Integer yi = new Integer(y); valueMap.put(x , yi); } public int LookupValue(Variable x) { int i = ((Integer)valueMap.get(x)).intValue(); return i ; } } [java] view plain copy
//抽象表达式角色,也可以用接口来实现 abstract class Expression { public abstract int interpret(Context con); } [java] view plain copy
//终结符表达式角色 class Constant extends Expression { private int i ; public Constant(int i) { this.i = i; } public int interpret(Context con) { return i ; } } [java] view plain copy
class Variable extends Expression { public int interpret(Context con) { //this为调用interpret方法的Variable对象 return con.LookupValue(this); } } [java] view plain copy
//非终结符表达式角色 class Add extends Expression { private Expression left ,right ; public Add(Expression left , Expression right) { this.left = left ; this.right= right ; } public int interpret(Context con) { return left.interpret(con) + right.interpret(con); } } [java] view plain copy
class Subtract extends Expression { private Expression left , right ; public Subtract(Expression left , Expression right) { this.left = left ; this.right= right ; } public int interpret(Context con) { return left.interpret(con) - right.interpret(con); } } [java] view plain copy
class Multiply extends Expression { private Expression left , right ; public Multiply(Expression left , Expression right) { this.left = left ; this.right= right ; } public int interpret(Context con) { return left.interpret(con) * right.interpret(con); } } [java] view plain copy
class Division extends Expression { private Expression left , right ; public Division(Expression left , Expression right) { this.left = left ; this.right= right ; } public int interpret(Context con) { try{ return left.interpret(con) / right.interpret(con); }catch(ArithmeticException ae) { System.out.println("被除数为0!"); return -11111; } } } [java] view plain copy
//测试程序,计算 (a*b)/(a-b+2) public class Test { private static Expression ex ; private static Context con ; public static void main(String[] args) { con = new Context(); //设置变量、常量 Variable a = new Variable(); Variable b = new Variable(); Constant c = new Constant(2); //为变量赋值 con.addValue(a , 5); con.addValue(b , 7); //运算,对句子的结构由我们自己来分析,构造 ex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c)); System.out.println("运算结果为:"+ex.interpret(con)); } } 解释器模式并没有说明如何创建一个抽象语法树,因此它的实现可以多种多样,在上面我们是直接在Test中提供的,当然还有更好、更专业的实现方式。
对于终结符,GOF建议采用享元模式来共享它们的拷贝,因为它们要多次重复出现。但是考虑到享元模式的使用局限性,我建议还是当你的系统中终结符重复的足够多的时候再考虑享元模式(关于享元模式,请参考我的《深入浅出享元模式》)。 四、优缺点
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。
但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊! 五、总结
这样对解释器模式应该有了些大体的认识了吧,由于这个模式使用的案例匮乏,所以本文大部分观点直接来自于GOF的原著。只是实例代码是亲自实现并调试通过的。
由于解释器模式基本不用,我就直接转载网上的了,大家看看涨涨姿势http://blog.csdn.net/ylchou/article/details/7594135
一、引子
其实没有什么好的例子引入解释器模式,因为它描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发编译器中;在实际应用中,我们可能很少碰到去构造一个语言的文法的情况。
虽然你几乎用不到这个模式,但是看一看还是能受到一定的启发的。
二、定义与结构
解释器模式的定义如下:定义语言的文法,并且建立一个解释器来解释该语言中的句子。它属于类的行为模式。这里的语言意思是使用规定格式和语法的代码。
在GOF的书中指出:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。而且当文法简单、效率不是关键问题的时候效果最好。
呵呵,这也就是解释器模式应用的环境了。
让我们来看看神秘的解释器模式是由什么来组成的吧。
1) 抽象表达式角色:声明一个抽象的解释操作,这个接口为所有具体表达式角色(抽象语法树中的节点)都要实现的。
什么叫做抽象语法树呢?《Java与模式》中给的解释为:抽象语法树的每一个节点都代表一个语句,而在每个节点上都可以执行解释方法。这个解释方法的执行就代表这个语句被解释。由于每一个语句都代表这个语句被解释。由于每一个语句都代表一个常见的问题的实例,因此每一个节点上的解释操作都代表对一个问题实例的解答。
2) 终结符表达式角色:具体表达式。
a) 实现与文法中的终结符相关联的解释操作
b) 而且句子中的每个终结符需要该类的一个实例与之对应
3) 非终结符表达式角色:具体表达式。
a) 文法中的每条规则R::=R1R2…Rn都需要一个非终结符表带式角色
b) 对于从R1到Rn的每个符号都维护一个抽象表达式角色的实例变量
c) 实现解释操作,解释一般要递归地调用表示从R1到Rn的那些对象的解释操作
4) 上下文(环境)角色:包含解释器之外的一些全局信息。
5) 客户角色:
a) 构建(或者被给定)表示该文法定义的语言中的一个特定的句子的抽象语法树
b) 调用解释操作
放上张解释器结构类图吧,这也是来自于GOF的书中。

呵呵,对每一个角色都给出了详细的职责,而且在类图中给出五个角色之间的关系。这样实现起来也不是很困难了,下面举了一个简单的例子,希望能加深你对解释器模式的理解。
三、举例
来举一个加减乘除的例子吧,实现思路来自于《java与模式》中的例子。每个角色的功能按照上面提到的规范来实现。
- //上下文(环境)角色,使用HashMap来存储变量对应的数值
- class Context
- {
- private Map valueMap = new HashMap();
- public void addValue(Variable x , int y)
- {
- Integer yi = new Integer(y);
- valueMap.put(x , yi);
- }
- public int LookupValue(Variable x)
- {
- int i = ((Integer)valueMap.get(x)).intValue();
- return i ;
- }
- }
- //抽象表达式角色,也可以用接口来实现
- abstract class Expression
- {
- public abstract int interpret(Context con);
- }
- //终结符表达式角色
- class Constant extends Expression
- {
- private int i ;
- public Constant(int i)
- {
- this.i = i;
- }
- public int interpret(Context con)
- {
- return i ;
- }
- }
- class Variable extends Expression
- {
- public int interpret(Context con)
- {
- //this为调用interpret方法的Variable对象
- return con.LookupValue(this);
- }
- }
- //非终结符表达式角色
- class Add extends Expression
- {
- private Expression left ,right ;
- public Add(Expression left , Expression right)
- {
- this.left = left ;
- this.right= right ;
- }
- public int interpret(Context con)
- {
- return left.interpret(con) + right.interpret(con);
- }
- }
- class Subtract extends Expression
- {
- private Expression left , right ;
- public Subtract(Expression left , Expression right)
- {
- this.left = left ;
- this.right= right ;
- }
- public int interpret(Context con)
- {
- return left.interpret(con) - right.interpret(con);
- }
- }
- class Multiply extends Expression
- {
- private Expression left , right ;
- public Multiply(Expression left , Expression right)
- {
- this.left = left ;
- this.right= right ;
- }
- public int interpret(Context con)
- {
- return left.interpret(con) * right.interpret(con);
- }
- }
- class Division extends Expression
- {
- private Expression left , right ;
- public Division(Expression left , Expression right)
- {
- this.left = left ;
- this.right= right ;
- }
- public int interpret(Context con)
- {
- try{
- return left.interpret(con) / right.interpret(con);
- }catch(ArithmeticException ae)
- {
- System.out.println("被除数为0!");
- return -11111;
- }
- }
- }
- //测试程序,计算 (a*b)/(a-b+2)
- public class Test
- {
- private static Expression ex ;
- private static Context con ;
- public static void main(String[] args)
- {
- con = new Context();
- //设置变量、常量
- Variable a = new Variable();
- Variable b = new Variable();
- Constant c = new Constant(2);
- //为变量赋值
- con.addValue(a , 5);
- con.addValue(b , 7);
- //运算,对句子的结构由我们自己来分析,构造
- ex = new Division(new Multiply(a , b), new Add(new Subtract(a , b) , c));
- System.out.println("运算结果为:"+ex.interpret(con));
- }
- }
解释器模式并没有说明如何创建一个抽象语法树,因此它的实现可以多种多样,在上面我们是直接在Test中提供的,当然还有更好、更专业的实现方式。
对于终结符,GOF建议采用享元模式来共享它们的拷贝,因为它们要多次重复出现。但是考虑到享元模式的使用局限性,我建议还是当你的系统中终结符重复的足够多的时候再考虑享元模式(关于享元模式,请参考我的《深入浅出享元模式》)。
四、优缺点
解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。
但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊!
五、总结
这样对解释器模式应该有了些大体的认识了吧,由于这个模式使用的案例匮乏,所以本文大部分观点直接来自于GOF的原著。只是实例代码是亲自实现并调试通过的。
interpreter(解释器模式)的更多相关文章
- 二十三、Interpreter 解释器模式
设计: 代码清单: Node public abstract class Node { public abstract void parse(Context context) throws Parse ...
- 设计模式15:Interpreter 解释器模式(行为型模式)
Interpreter 解释器模式(行为型模式) 动机(Motivation) 在软件构建过程中,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变 ...
- 23、Interpreter 解释器模式
1.Interpreter 解释器模式 解释器模式是一种使用频率相对较低但学习难度较大的设计模式,它用于描述如何使用面向对象语言构成一个简单的语言解释器.在某些情况下,为了更好地描述某一些特定类型的问 ...
- 面向对象设计模式之Interpreter解释器模式(行为型)
动机:在软件构建过程中 ,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化.在这种情况下,将特定领域的问题表达为某种语法规则的句子,然后构建一个 ...
- 设计模式(15)--Interpreter(解释器模式)--行为型
作者QQ:1095737364 QQ群:123300273 欢迎加入! 1.模式定义: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解 ...
- 设计模式之解释器模式(Interpreter)摘录
23种GOF设计模式一般分为三大类:创建型模式.结构型模式.行为模式. 创建型模式抽象了实例化过程,它们帮助一个系统独立于怎样创建.组合和表示它的那些对象.一个类创建型模式使用继承改变被实例化的类,而 ...
- [工作中的设计模式]解释器模式模式Interpreter
一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...
- 深入浅出设计模式——解释器模式(Interpreter Pattern)
模式动机 如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题.解释器模式描述了如何构成一个 ...
- [设计模式] 15 解释器模式 Interpreter
在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类 ...
随机推荐
- Enterprise Solution 3.1 企业应用开发框架 .NET ERP/CRM/MIS 开发框架,C/S架构,SQL Server + ORM(LLBL Gen Pro) + Infragistics WinForms
行业:基于数据库的制造行业管理软件,包含ERP.MRP.CRM.MIS.MES等企业管理软件 数据库平台:SQL Server 2005或以上 系统架构:C/S 开发技术 序号 领域 技术 1 数据库 ...
- jsp页面无法识别el表达式的解决方案
今天在写一个springmvc的小demo时,碰到一个问题,在jsp页面中书写为${user.username}的表达式语言,在浏览器页面中仍然显示为${user.username},说明jsp根本不 ...
- 搭建属于自己的VIP积分系统(1)
很久没写博客了,如果有写得不好的地方,还请多多见谅. 架构设计 需求分析 这篇文章主要是介绍此VIP系统的基础架构.说实在的,我其实对 架构方面也不是很懂,我这套框架 还是拿别人的东西改过来的,并不是 ...
- c#语言规范
0x00 分类 C#语言规范主要有两个来源,即我们熟知的ECMA规范和微软的规范.尽管C#的ECMA规范已经前后修订4次,但其内容仅仅到C# 2.0为止.所以慕容为了方便自己和各位方便查询,在此将常见 ...
- BridgePattern(桥接模式)
/** * 桥接模式 * @author TMAC-J * 应用于多维度方案 * 用组合的形式代替继承 * 符合单一职责原则 * 一个类只有一个引起他变化的原因 * 增加程序灵活性 */ public ...
- Extjs 让combobox写起来更简单
也已经写了很久时间的extjs ,每次都用到很多的combobox,配置很多东西觉得实在是太麻烦,所以根据常用到的情况写了一个简便的combobox,再次记录下来,以免放在某个地方忘记了找不到了. 定 ...
- js 基础篇(点击事件轮播图的实现)
轮播图在以后的应用中还是比较常见的,不需要多少行代码就能实现.但是在只掌握了js基础知识的情况下,怎么来用较少的而且逻辑又简单的方法来实现呢?下面来分析下几种不同的做法: 1.利用位移的方法来实现 首 ...
- iOS之ProtocolBuffer搭建和示例demo
这次搭建iOS的ProtocolBuffer编译器和把*.proto源文件编译成*.pbobjc.h 和 *.pbobjc.m文件时,碰到不少问题! 搭建pb编译器到时没有什么问题,只是在把*.pro ...
- jQuery 的选择器常用的元素查找方法
jQuery 的选择器常用的元素查找方法 基本选择器: $("#myELement") 选择id值等于myElement的元素,id值不能重复在文档中只能有一个id值是myE ...
- maven常见异常以及解决方法
本文写的是我在整合ssm框架时遇到的一些问题,我估计很多人也会遇到,所以,这里作为一个总结,希望能够帮助大家解决问题 一,加入shiro组件时抛出的异常 加入步骤(略) 问题 1,保存后,无法导入sh ...