设计模式:解释器模式(Interpreter)
为人处事是一门大学问,察言观色、听懂弦外之音都是非常重要的,老板跟你说“XX你最近表现平平啊,还得要多努力”,如果你不当回事,平常对待,可能下次就是“XX,恩,你人还是不错,平常工作也很努力,但是我想这份工作可能不是很适合你…..”。又比如你老大说“XX,你最近表现不错,工作积极性很高啊!继续保持啊!”,你高兴乐呵着心想是不是老板要给我加工资了,可能你等到花都谢了也没有,得到的可能会是更多的工作量。对于我们刚刚入社会的人不够圆滑,不会察言观色,更听不懂老板的弦外之音,所以我们期待如果有一个翻译机该多好,直接将别人的弦外之音给翻译出来就好了。
在我们实际的生活中是这样,在软件的世界里也同样存在着翻译机,只不过在软件中我们称之为解释器。在系统中如果某一特定类型的问题在频繁的发生,此时我们就有必要将这些问题的实例表述为一个语言中句子,因此可以构建一个解释器,然后利用该解释器来解释这些句子来解决这些问题。

一、 模式定义
所谓解释器模式就是定义语言的文法,并且建立一个解释器来解释该语言中的句子。
在这里我们将语言理解成使用规定格式和语法的代码。
在前面我们知道可以构建解释器来解决那些频繁发生的某一特定类型的问题,在这我们将这些问题的实例表述为一个语言中句子。例如我经常利用正则表达式来检测某些字符串是否符合我们规定的格式。这里正则表达式就是解释器模式的应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。
解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中。它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。
在解释器模式中除了能够使用文法规则来定义一个语言,还有通过一个更加直观的方法来表示——使用抽象语法树。抽象语法树能够更好地,更直观地表示一个语言的构成,每一颗抽象语法树对应一个语言实例。

二、 模式结构
下图是解释器模式的UML结构图。

解释器模式主要包含如下几个角色:
AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
Context: 环境类。包含解释器之外的一些全局信息。
Client: 客户类。
抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。
三、 模式实现
现在我们用解释器模式来实现一个基本的加、减、乘、除和求模运算。例如用户输入表达式“3 * 4 / 2 % 4”,输出结果为2。下图为该实例的UML结构图:

抽象语法树

实现过程:
抽象表达式:Node.java。
public interface Node
{
public int interpret();
}
非终结表达式:ValueNode.java。主要用解释该表达式的值。

public class ValueNode implements Node
{
private int value; public ValueNode(int value)
{
this.value=value;
} public int interpret()
{
return this.value;
}
}

终结表达式抽象类,由于该终结表达式需要解释多个运算符号,同时用来构建抽象语法树:

public abstract class SymbolNode implements Node
{
protected Node left;
protected Node right; public SymbolNode(Node left,Node right)
{
this.left=left;
this.right=right;
}
}

MulNode.java

public class MulNode extends SymbolNode
{
public MulNode(Node left,Node right)
{
super(left,right);
} public int interpret()
{
return left.interpret() * right.interpret();
}
}

ModNode.java

public class ModNode extends SymbolNode{
public ModNode(Node left,Node right){
super(left,right);
}
public int interpret(){
return super.left.interpret() % super.right.interpret();
}
}

DivNode.java

public class DivNode extends SymbolNode{
public DivNode(Node left,Node right){
super(left,right);
}
public int interpret(){
return super.left.interpret() / super.right.interpret();
}
}

Calculator.java

public class Calculator{
private String statement;
private Node node;
public void build(String statement){
Node left=null,right=null;
Stack stack=new Stack();
String[] statementArr=statement.split(" ");
for(int i=0;i<statementArr.length;i++){
if(statementArr[i].equalsIgnoreCase("*")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new MulNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("/")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new DivNode(left,right));
}
else if(statementArr[i].equalsIgnoreCase("%")){
left=(Node)stack.pop();
int val=Integer.parseInt(statementArr[++i]);
right=new ValueNode(val);
stack.push(new ModNode(left,right));
}
else{
stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
}
}
this.node=(Node)stack.pop();
}
public int compute()
return node.interpret();
}
}

客户端:Client.java

public class Client{
public static void main(String args[]){
String statement = "3 * 2 * 4 / 6 % 5";
Calculator calculator = new Calculator();
calculator.build(statement);
int result = calculator.compute();
System.out.println(statement + " = " + result);
}
}

运行结果:3 * 2 * 4 / 6 % 5 = 4
四、 模式优缺点
优点
1、 可扩展性比较好,灵活。
2、 增加了新的解释表达式的方式。
3、 易于实现文法。
缺点
1、 执行效率比较低,可利用场景比较少。
2、 对于复杂的文法比较难维护。
五、 模式适用场景
1、可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
2、一些重复出现的问题可以用一种简单的语言来进行表达。
3、文法较为简单。
六、 模式总结
1、在解释器模式中由于语法是由很多类表示的,所以可扩展性强。
2、虽然解释器的可扩展性强,但是如果语法规则的数目太大的时候,该模式可能就会变得异常复杂。所以解释器模式适用于文法较为简单的。
3、解释器模式可以处理脚本语言和编程语言。常用于解决某一特定类型的问题频繁发生情况。
设计模式:解释器模式(Interpreter)的更多相关文章
- javascript设计模式 - 解释器模式(interpreter)
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 大话设计模式--解释器模式 interpreter -- C++实现实例
1. 解释器模式: 给定一个语言,定义它的文法的一种表示 并 定义一个解释器,这个解释器使用该表示文法 来解释语言中的句子. 如果一种特定类型的问题发生的频率很高,那么可能就值得将该问题的各个实例表述 ...
- C#设计模式——解释器模式(Interpreter Pattern)
一.概述 在软件开发特别是DSL开发中常常需要使用一些相对较复杂的业务语言,如果业务语言使用频率足够高,且使用普通的编程模式来实现会导致非常复杂的变化,那么就可以考虑使用解释器模式构建一个解释器对复杂 ...
- 深入浅出设计模式——解释器模式(Interpreter Pattern)
模式动机 如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题.解释器模式描述了如何构成一个 ...
- 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern)
原文:乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) [索引页][源码下载] 乐在其中设计模式(C#) - 解释器模式(Interpreter Pattern) 作 ...
- 解释器模式 Interpreter 行为型 设计模式(十九)
解释器模式(Interpreter) 考虑上图中计算器的例子 设计可以用于计算加减运算(简单起见,省略乘除),你会怎么做? 你可能会定义一个工具类,工具类中有N多静态方法 比如定义了两个 ...
- C#设计模式:解释器模式(Interpreter Pattern)
一,C#设计模式:解释器模式(Interpreter Pattern) 1,解释器模式的应用场合是Interpreter模式应用中的难点,只有满足“业务规则频繁变化,且类似的模式不断重复出现,并且容易 ...
- 二十四种设计模式:解释器模式(Interpreter Pattern)
解释器模式(Interpreter Pattern) 介绍给定一个语言, 定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. 示例有一个Message实体类,某个类对它的 ...
- JAVA 设计模式 解释器模式
用途 解释器模式 (Interpreter) 定义一个语言,定义它的文法的一种表示. 并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 解释器模式是一种行为型模式. 结构
随机推荐
- fhq Treap(无旋Treap)
先吹一波fhq dalao,竟然和我一个姓,我真是给他丢脸. 昨天treap就搞了一下午,感觉自己弱爆了.然后今天上午又看了一个上午的无旋treap再次懵逼,我太弱了,orzorz. 所以写个博客防止 ...
- delphi中Tkbmmemtable数据转成SQL脚本
unit UMemtableToSql; interface uses SysUtils, Classes, DB, kbmMemTable, Variants, Dialogs, SuperObje ...
- TensorFlow使用记录 (七): BN 层及 Dropout 层的使用
参考:tensorflow中的batch_norm以及tf.control_dependencies和tf.GraphKeys.UPDATE_OPS的探究 1. Batch Normalization ...
- codeforces613E
Puzzle Lover CodeForces - 613E Oleg Petrov loves crossword puzzles and every Thursday he buys his fa ...
- Django-rbac权限
1.注册应用rbac 2.设计表 权限表 角色表 用户表 不同角色有不同的权限,给每个用户分配不同的角色(一个用户可以有多个角色) 3.数据注入 将数据注入在rbac中封装成一个函数 4.权限认证是在 ...
- [BJOI2015]树的同构 && 树哈希教程
题目链接 有根树的哈希 离散数学中对树哈希的描述在这里.大家可以看看. 判断有根树是否同构,可以考虑将有根树编码.而编码过程中,要求保留树形态的特征,同时忽略子树顺序的不同.先来看一看这个方法: 不妨 ...
- E. Compress Words(Hash,KMP)
E. Compress Words time limit per test 1 second memory limit per test 256 megabytes input standard in ...
- Data Science Competition中的工具汇总
除了基础的pandas,scikit-learn,numpy,matplotlib,seaborn以外 ( 1 ) category_encoders github 属于scikit-learn co ...
- Hadoop-2.7.5完全分布式搭建
1.在虚拟机上安装Hadoop完全分布式准备工作 1)这里使用的是VMWare软件,在VMWare上安装一个CentOS6.5,并再克隆两个机器配置相关MAC地址,以及配置机器名 2)三台虚拟机配置好 ...
- OpenStack Blazar 架构解析与功能实践
目录 文章目录 目录 Blazar Blazar 的安装部署 Blazar 的软件架构 Blazar 的资源模型与状态机 Blazar 的主机资源预留功能(Host Reservation) 代码实现 ...