文档章节

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

Simon丶Ma
 Simon丶Ma
发布于 2016/04/14 14:41
字数 2812
阅读 3
收藏 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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:08:58
 * 
 * @类说明 :抽象表达式角色
 */
public abstract class Expression {
	/**
	 * 以环境为准,本方法解释给定的任何一个表达式
	 */
	public abstract boolean interpret(Context ctx);

	/**
	 * 检验两个表达式在结构上是否相同
	 */
	public abstract boolean equals(Object obj);

	/**
	 * 返回表达式的hash code
	 */
	public abstract int hashCode();

	/**
	 * 将表达式转换成字符串
	 */
	public abstract String toString();
}


  一个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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:09:35
 * 
 * @类说明 :一个Constant对象代表一个布尔常量
 */
public class Constant extends Expression {

	private boolean value;

	public Constant(boolean value) {
		this.value = value;
	}

	@Override
	public boolean equals(Object obj) {

		if (obj != null && obj instanceof Constant) {
			return this.value == ((Constant) obj).value;
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public boolean interpret(Context ctx) {

		return value;
	}

	@Override
	public String toString() {
		return new Boolean(value).toString();
	}

}


  一个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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:10:16
 * 
 * @类说明 :一个Variable对象代表一个有名变量
 */
public class Variable extends Expression {

	private String name;

	public Variable(String name) {
		this.name = name;
	}

	@Override
	public boolean equals(Object obj) {

		if (obj != null && obj instanceof Variable) {
			return this.name.equals(((Variable) obj).name);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public String toString() {
		return name;
	}

	@Override
	public boolean interpret(Context ctx) {
		return ctx.lookup(this);
	}

}


  代表逻辑“与”操作的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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:10:55
 * 
 * @类说明 :代表逻辑“与”操作的And类,表示由两个布尔表达式通过逻辑“与”操作给出一个新的布尔表达式的操作
 */
public class And extends Expression {

	private Expression left, right;

	public And(Expression left, Expression right) {
		this.left = left;
		this.right = right;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && obj instanceof And) {
			return left.equals(((And) obj).left) && right.equals(((And) obj).right);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public boolean interpret(Context ctx) {

		return left.interpret(ctx) && right.interpret(ctx);
	}

	@Override
	public String toString() {
		return "(" + left.toString() + " AND " + right.toString() + ")";
	}

}


  代表逻辑“或”操作的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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:11:20
 * 
 * @类说明 :代表逻辑“或”操作的Or类,代表由两个布尔表达式通过逻辑“或”操作给出一个新的布尔表达式的操作
 */
public class Or extends Expression {
	private Expression left, right;

	public Or(Expression left, Expression right) {
		this.left = left;
		this.right = right;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && obj instanceof Or) {
			return this.left.equals(((Or) obj).left) && this.right.equals(((Or) obj).right);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public boolean interpret(Context ctx) {
		return left.interpret(ctx) || right.interpret(ctx);
	}

	@Override
	public String toString() {
		return "(" + left.toString() + " OR " + right.toString() + ")";
	}

}


  代表逻辑“非”操作的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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:11:36
 * 
 * @类说明 :代表逻辑“非”操作的Not类,代表由一个布尔表达式通过逻辑“非”操作给出一个新的布尔表达式的操作
 */
public class Not extends Expression {

	private Expression exp;

	public Not(Expression exp) {
		this.exp = exp;
	}

	@Override
	public boolean equals(Object obj) {
		if (obj != null && obj instanceof Not) {
			return exp.equals(((Not) obj).exp);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return this.toString().hashCode();
	}

	@Override
	public boolean interpret(Context ctx) {
		return !exp.interpret(ctx);
	}

	@Override
	public String toString() {
		return "(Not " + exp.toString() + ")";
	}

}


 

  环境(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. }  
package com.bankht.Interpreter;

import java.util.HashMap;
import java.util.Map;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:11:54
 * 
 * @类说明 :环境(Context)类定义出从变量到布尔值的一个映射
 */
public class Context {

	private Map<Variable, Boolean> map = new HashMap<Variable, Boolean>();

	public void assign(Variable var, boolean value) {
		map.put(var, new Boolean(value));
	}

	public boolean lookup(Variable var) throws IllegalArgumentException {
		Boolean value = map.get(var);
		if (value == null) {
			throw new IllegalArgumentException();
		}
		return value.booleanValue();
	}
}


  客户端类

 
  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. }  
package com.bankht.Interpreter;

/**
 * @author: 特种兵—AK47
 * @创建时间:2012-7-3 下午03:12:17
 * 
 * @类说明 :客户端类
 */
public class Client {

	public static void main(String[] args) {
		Context 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);

		Expression 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));
	}

}


  运行结果如下:

 

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

 

 

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

© 著作权归作者所有

Simon丶Ma
粉丝 4
博文 134
码字总数 299850
作品 0
深圳
程序员
私信 提问
设计模式 2014-12-19

book: 阎宏《JAVA与模式》 架构设计栏目 http://blog.csdn.net/enterprise/column.html 概要: http://bbs.csdn.net/forums/Embeddeddriver 23种设计模式分别是: 1.单例模式 2.工厂方法模式...

jayronwang
2014/12/19
309
0
java 23种设计模式 深入理解

以下是学习过程中查询的资料,别人总结的资料,比较容易理解(站在各位巨人的肩膀上,望博主勿究) 创建型 抽象工厂模式 http://www.cnblogs.com/java-my-life/archive/2012/03/28/2418836.html ...

wc_飞豆
2018/03/16
223
0
设计模式15——Template Method设计模式

Template Method模板方法设计模式定义一个操作中算法的骨架,将具体步骤的执行延迟到子类中实现。Java中的抽象类就是使用了模板方法设计模式。模板方法设计模式结构如下: 以文档处理为例,T...

小米米儿小
2014/01/24
239
0
java中23种设计模式(上)

参考网址:http://blog.csdn.net/zhangerqing 资源:http://download.csdn.net/detail/zhangerqing/4835830 设计模式(Design Patterns) 设计模式(Design pattern)是一套被反复使用、多数...

青涩的梦
2018/06/26
0
0
练就Java24章真经—你所不知道的工厂方法

前言 最近一直在Java方向奋斗《终于,我还是下决心学Java后台了》,今天抽空开始学习Java的设计模式了 。计划有时间就去学习,你这么有时间,还不来一起上车吗? 之所以要学习Java模式,是因...

codeGoogle
2018/10/30
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何有效地计算JavaScript中对象的键/属性数量?

计算对象的键/属性数的最快方法是什么? 是否可以在不迭代对象的情况下执行此操作? 即不做 var count = 0;for (k in myobj) if (myobj.hasOwnProperty(k)) count++; (Firefox确实提供了一...

技术盛宴
19分钟前
2
0
百度网址安全中心拦截解除的办法分享

临近2019年底,客户的公司网站被百度网址安全中心拦截了,公司网站彻底打不开了,影响范围很大,于是通过朋友介绍找到我们SINE安全公司寻求帮忙解封,关于如何解除百度的安全拦截提示,下面就...

网站安全
30分钟前
3
0
Tomcat8源码分析-启动流程-start方法

上一篇:Tomcat8源码分析-启动流程-load方法 前面讲了启动流程中的Catalina.load,进一步调用绝大部分组建的init操作,主要完成对server.xml解析,并根据解析的结果结合设置的Rule(规则)构造...

特拉仔
39分钟前
6
0
Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍

Xamarin.FormsShell基础教程(7)Shell项目关于页面的介绍 轻拍标签栏中的About标签,进入关于页面,如图1.8和图1.9所示。它是对应用程序介绍的页面。 该页面源自Views文件夹中的AboutPage.x...

大学霸
45分钟前
3
0
一步一步理解Impala query profile(一)

很多Impala用户不知道如何阅读Impala query profile来了解一个查询背后正在执行的操作,从而在此基础上对查询进行调优以充分发挥查询的性能。因此我想写一篇简单的文章来分享我的经验,并希望...

九州暮云
46分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部