码迷,mamicode.com
首页 > 编程语言 > 详细

《Java设计模式》之解释器模式

时间:2015-08-21 19:30:36      阅读:254      评论:0      收藏:0      [点我收藏+]

标签:

解释器模式是类的行为模式。给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器。客户端可以使用这个解释器来解释这个语言中的句子。

解释器模式的结构

  下面就以一个示意性的系统为例,讨论解释器模式的结构。系统的结构图如下所示:

技术分享

  模式所涉及的角色如下所示:

  (1)抽象表达式(Expression)角色:声明一个所有的具体表达式角色都需要实现的抽象接口。这个接口主要是一个interpret()方法,称做解释操作。

  (2)终结符表达式(Terminal Expression)角色:实现了抽象表达式角色所要求的接口,主要是一个interpret()方法;文法中的每一个终结符都有一个具体终结表达式与之相对应。比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。

  (3)非终结符表达式(Nonterminal Expression)角色:文法中的每一条规则都需要一个具体的非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式。

  (4)环境(Context)角色:这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如R=R1+R2,我们给R1赋值100,给R2赋值200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。

 

  为了说明解释器模式的实现办法,这里给出一个最简单的文法和对应的解释器模式的实现,这就是模拟Java语言中对布尔表达式进行操作和求值。

  在这个语言中终结符是布尔变量,也就是常量true和false。非终结符表达式包含运算符and,or和not等布尔表达式。这个简单的文法如下:

    Expression    ::= Constant | Variable | Or | And | Not

    And     ::= Expression ‘AND‘ Expression

    Or     ::= Expression ‘OR‘ Expression

    Not       ::= ‘NOT‘ Expression

    Variable   ::= 任何标识符

    Constant         ::= ‘true‘ | ‘false‘

  解释器模式的结构图如下所示:

 

技术分享

  源代码

  抽象表达式角色

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:08:58 
  6.  *  
  7.  * @类说明 :抽象表达式角色 
  8.  */  
  9. public abstract class Expression {  
  10.     /** 
  11.      * 以环境为准,本方法解释给定的任何一个表达式 
  12.      */  
  13.     public abstract boolean interpret(Context ctx);  
  14.   
  15.     /** 
  16.      * 检验两个表达式在结构上是否相同 
  17.      */  
  18.     public abstract boolean equals(Object obj);  
  19.   
  20.     /** 
  21.      * 返回表达式的hash code 
  22.      */  
  23.     public abstract int hashCode();  
  24.   
  25.     /** 
  26.      * 将表达式转换成字符串 
  27.      */  
  28.     public abstract String toString();  
  29. }  


  一个Constant对象代表一个布尔常量

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:09:35 
  6.  *  
  7.  * @类说明 :一个Constant对象代表一个布尔常量 
  8.  */  
  9. public class Constant extends Expression {  
  10.   
  11.     private boolean value;  
  12.   
  13.     public Constant(boolean value) {  
  14.         this.value = value;  
  15.     }  
  16.   
  17.     @Override  
  18.     public boolean equals(Object obj) {  
  19.   
  20.         if (obj != null && obj instanceof Constant) {  
  21.             return this.value == ((Constant) obj).value;  
  22.         }  
  23.         return false;  
  24.     }  
  25.   
  26.     @Override  
  27.     public int hashCode() {  
  28.         return this.toString().hashCode();  
  29.     }  
  30.   
  31.     @Override  
  32.     public boolean interpret(Context ctx) {  
  33.   
  34.         return value;  
  35.     }  
  36.   
  37.     @Override  
  38.     public String toString() {  
  39.         return new Boolean(value).toString();  
  40.     }  
  41.   
  42. }  


  一个Variable对象代表一个有名变量

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:10:16 
  6.  *  
  7.  * @类说明 :一个Variable对象代表一个有名变量 
  8.  */  
  9. public class Variable extends Expression {  
  10.   
  11.     private String name;  
  12.   
  13.     public Variable(String name) {  
  14.         this.name = name;  
  15.     }  
  16.   
  17.     @Override  
  18.     public boolean equals(Object obj) {  
  19.   
  20.         if (obj != null && obj instanceof Variable) {  
  21.             return this.name.equals(((Variable) obj).name);  
  22.         }  
  23.         return false;  
  24.     }  
  25.   
  26.     @Override  
  27.     public int hashCode() {  
  28.         return this.toString().hashCode();  
  29.     }  
  30.   
  31.     @Override  
  32.     public String toString() {  
  33.         return name;  
  34.     }  
  35.   
  36.     @Override  
  37.     public boolean interpret(Context ctx) {  
  38.         return ctx.lookup(this);  
  39.     }  
  40.   
  41. }  


  代表逻辑“与”操作的And类,表示由两个布尔表达式通过逻辑“与”操作给出一个新的布尔表达式的操作

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:10:55 
  6.  *  
  7.  * @类说明 :代表逻辑“与”操作的And类,表示由两个布尔表达式通过逻辑“与”操作给出一个新的布尔表达式的操作 
  8.  */  
  9. public class And extends Expression {  
  10.   
  11.     private Expression left, right;  
  12.   
  13.     public And(Expression left, Expression right) {  
  14.         this.left = left;  
  15.         this.right = right;  
  16.     }  
  17.   
  18.     @Override  
  19.     public boolean equals(Object obj) {  
  20.         if (obj != null && obj instanceof And) {  
  21.             return left.equals(((And) obj).left) && right.equals(((And) obj).right);  
  22.         }  
  23.         return false;  
  24.     }  
  25.   
  26.     @Override  
  27.     public int hashCode() {  
  28.         return this.toString().hashCode();  
  29.     }  
  30.   
  31.     @Override  
  32.     public boolean interpret(Context ctx) {  
  33.   
  34.         return left.interpret(ctx) && right.interpret(ctx);  
  35.     }  
  36.   
  37.     @Override  
  38.     public String toString() {  
  39.         return "(" + left.toString() + " AND " + right.toString() + ")";  
  40.     }  
  41.   
  42. }  


  代表逻辑“或”操作的Or类,代表由两个布尔表达式通过逻辑“或”操作给出一个新的布尔表达式的操作

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:11:20 
  6.  *  
  7.  * @类说明 :代表逻辑“或”操作的Or类,代表由两个布尔表达式通过逻辑“或”操作给出一个新的布尔表达式的操作 
  8.  */  
  9. public class Or extends Expression {  
  10.     private Expression left, right;  
  11.   
  12.     public Or(Expression left, Expression right) {  
  13.         this.left = left;  
  14.         this.right = right;  
  15.     }  
  16.   
  17.     @Override  
  18.     public boolean equals(Object obj) {  
  19.         if (obj != null && obj instanceof Or) {  
  20.             return this.left.equals(((Or) obj).left) && this.right.equals(((Or) obj).right);  
  21.         }  
  22.         return false;  
  23.     }  
  24.   
  25.     @Override  
  26.     public int hashCode() {  
  27.         return this.toString().hashCode();  
  28.     }  
  29.   
  30.     @Override  
  31.     public boolean interpret(Context ctx) {  
  32.         return left.interpret(ctx) || right.interpret(ctx);  
  33.     }  
  34.   
  35.     @Override  
  36.     public String toString() {  
  37.         return "(" + left.toString() + " OR " + right.toString() + ")";  
  38.     }  
  39.   
  40. }  


  代表逻辑“非”操作的Not类,代表由一个布尔表达式通过逻辑“非”操作给出一个新的布尔表达式的操作

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:11:36 
  6.  *  
  7.  * @类说明 :代表逻辑“非”操作的Not类,代表由一个布尔表达式通过逻辑“非”操作给出一个新的布尔表达式的操作 
  8.  */  
  9. public class Not extends Expression {  
  10.   
  11.     private Expression exp;  
  12.   
  13.     public Not(Expression exp) {  
  14.         this.exp = exp;  
  15.     }  
  16.   
  17.     @Override  
  18.     public boolean equals(Object obj) {  
  19.         if (obj != null && obj instanceof Not) {  
  20.             return exp.equals(((Not) obj).exp);  
  21.         }  
  22.         return false;  
  23.     }  
  24.   
  25.     @Override  
  26.     public int hashCode() {  
  27.         return this.toString().hashCode();  
  28.     }  
  29.   
  30.     @Override  
  31.     public boolean interpret(Context ctx) {  
  32.         return !exp.interpret(ctx);  
  33.     }  
  34.   
  35.     @Override  
  36.     public String toString() {  
  37.         return "(Not " + exp.toString() + ")";  
  38.     }  
  39.   
  40. }  


 

  环境(Context)类定义出从变量到布尔值的一个映射

 

 
  1. package com.bankht.Interpreter;  
  2.   
  3. import java.util.HashMap;  
  4. import java.util.Map;  
  5.   
  6. /** 
  7.  * @author: 特种兵—AK47 
  8.  * @创建时间:2012-7-3 下午03:11:54 
  9.  *  
  10.  * @类说明 :环境(Context)类定义出从变量到布尔值的一个映射 
  11.  */  
  12. public class Context {  
  13.   
  14.     private Map<Variable, Boolean> map = new HashMap<Variable, Boolean>();  
  15.   
  16.     public void assign(Variable var, boolean value) {  
  17.         map.put(var, new Boolean(value));  
  18.     }  
  19.   
  20.     public boolean lookup(Variable var) throws IllegalArgumentException {  
  21.         Boolean value = map.get(var);  
  22.         if (value == null) {  
  23.             throw new IllegalArgumentException();  
  24.         }  
  25.         return value.booleanValue();  
  26.     }  
  27. }  


  客户端类

 
  1. package com.bankht.Interpreter;  
  2.   
  3. /** 
  4.  * @author: 特种兵—AK47 
  5.  * @创建时间:2012-7-3 下午03:12:17 
  6.  *  
  7.  * @类说明 :客户端类 
  8.  */  
  9. public class Client {  
  10.   
  11.     public static void main(String[] args) {  
  12.         Context ctx = new Context();  
  13.         Variable x = new Variable("x");  
  14.         Variable y = new Variable("y");  
  15.         Constant c = new Constant(true);  
  16.         ctx.assign(x, false);  
  17.         ctx.assign(y, true);  
  18.   
  19.         Expression exp = new Or(new And(c, x), new And(y, new Not(x)));  
  20.         System.out.println("x=" + x.interpret(ctx));  
  21.         System.out.println("y=" + y.interpret(ctx));  
  22.         System.out.println(exp.toString() + "=" + exp.interpret(ctx));  
  23.     }  
  24.   
  25. }  


  运行结果如下:

 

x=false  

y=true  

((true AND x) OR (y AND (Not x)))=true  

 

 

四、优缺点

解释器模式提供了一个简单的方式来执行语法,而且容易修改或者扩展语法。一般系统中很多类使用相似的语法,可以使用一个解释器来代替为每一个规则实现一个解释器。而且在解释器中不同的规则是由不同的类来实现的,这样使得添加一个新的语法规则变得简单。

但是解释器模式对于复杂文法难以维护。可以想象一下,每一个规则要对应一个处理类,而且这些类还要递归调用抽象表达式角色,多如乱麻的类交织在一起是多么恐怖的一件事啊!

 

五、总结

这样对解释器模式应该有了些大体的认识了吧,由于这个模式使用的案例匮乏,所以本文大部分观点直接来自于GOF的原著。只是实例代码是亲自实现并调试通过的。

 

 

 

本文借鉴:

http://www.cnblogs.com/jingmoxukong/p/4236961.html

http://blog.csdn.net/hfmbook/article/details/7688593

http://blog.csdn.net/ylchou/article/details/7594135

http://blog.csdn.net/m13666368773/article/details/7712110

 

 

版权声明:欢迎转载,希望在你转载的同时,添加原文地址,谢谢配合

《Java设计模式》之解释器模式

标签:

原文地址:http://blog.csdn.net/u011225629/article/details/47838577

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!