解释器模式

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

意图 给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。

主要解决 对于一些固定文法构建一个解释句子的解释器。

何时使用 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

如何解决 构件语法树,定义终结符与非终结符。

关键代码 构件环境类,包含解释器之外的一些全局信息,一般是 HashMap。

解释器模式相关UML图

类图

可以看出右侧的协作图(object collaboration diagram)展现出运行时的解释器模式。Client向右侧抽象语法树发送解释请求,请求被转发并向下到树结构的所有对象。

解释器模式的主要角色

抽象解释器(AbstractExpression/Expression):声明一个所有具体表达式都要实现的抽象接口(或者抽象类),接口中主要是一个interpret()方法,称为解释操作。具体解释任务由它的各个实现类来完成,具体的解释器分别由终结符解释器TerminalExpression和非终结符解释器NonterminalExpression完成。

终结符表达式(TerminalExpression):实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一半是文法中的运算单元,比如有一个简单的公式R=R1+R2,在里面R1和R2就是终结符,对应的解析R1和R2的解释器就是终结符表达式。

非终结符表达式(NonterminalExpression):文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式R=R1+R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。

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

干货代码

跳转到源码地址

简单的一个解释器计算加减乘除算法,环境上下文没有用好,其实计算规则更多的是人为设定的了。

本次的抽象接收器用的是抽象类,用接口代替也可以。

//抽象解释器
public abstract class AbstractExpression { public abstract int interpreter(Context context);
} //非终结表达式:加法
@Data
@AllArgsConstructor
public class Add extends AbstractExpression { private final AbstractExpression left; private final AbstractExpression right; @Override
public int interpreter(Context context) {
return left.interpreter(context) + right.interpreter(context);
}
} //非终结表达式:减法
@Data
@AllArgsConstructor
public class Subtract extends AbstractExpression { private final AbstractExpression left; private final AbstractExpression right; @Override
public int interpreter(Context context) {
return left.interpreter(context) - right.interpreter(context);
}
} //非终结表达式:乘法
@Data
@AllArgsConstructor
public class Multiply extends AbstractExpression { private final AbstractExpression left; private final AbstractExpression right; @Override
public int interpreter(Context context) {
return left.interpreter(context) * right.interpreter(context);
}
} //非终结表达式:除法
@Data
@AllArgsConstructor
public class Division extends AbstractExpression { private final AbstractExpression left; private final AbstractExpression right; @Override
public int interpreter(Context context) {
int right = this.right.interpreter(context);
if (right != 0) {
return left.interpreter(context) / right;
} return -1;
}
} //终结表达式:变量
@Data
@AllArgsConstructor
public class Variable extends AbstractExpression { private final String key; @Override
public int interpreter(Context context) {
return context.getValue(key);
}
} //环境上下文
@Getter
public class Context { private final Map<String, Integer> valueMap = Maps.newHashMap(); public void addValue(final String key, final int value) {
valueMap.put(key, Integer.valueOf(value));
} public int getValue(final String key) {
return valueMap.get(key).intValue();
}
} //
public class Application { public static void main(String[] args) {
Context context = new Context();
context.addValue("a", 6);
context.addValue("b", 9);
context.addValue("c", 1); Variable a = new Variable("a");
Variable b = new Variable("b");
Variable c = new Variable("c"); AbstractExpression multiplyValue = new Multiply(a, b);
AbstractExpression subtractValue = new Subtract(a, b);
AbstractExpression addValue = new Add(subtractValue, c);
AbstractExpression divisionValue = new Division(multiplyValue, addValue); log.info("{}", context.getValueMap());
log.info("(a*b)/(a-b+c) = {}", divisionValue.interpreter(context));
}
}

结果如下:

Java中的应用

java中的表达式引擎

parsii

JEval

JEPLite

expr

Janino

MathEval

Java表达式引擎fel/groovy/expression4j/java脚本引擎的性能对比

JDK中的应用

这个模式通常定义了一个语言的语法,然后解析相应语法的语句。

java.util.Pattern

java.text.Normalizer

java.text.Format

参考

解释器模式|菜鸟教程

Interpreter pattern

细数JDK里的设计模式

23种设计模式(14):解释器模式

折腾Java设计模式之解释器模式的更多相关文章

  1. 折腾Java设计模式之建造者模式

    博文原址:折腾Java设计模式之建造者模式 建造者模式 Separate the construction of a complex object from its representation, a ...

  2. 折腾Java设计模式之备忘录模式

    原文地址:折腾Java设计模式之备忘录模式 备忘录模式 Without violating encapsulation, capture and externalize an object's int ...

  3. 折腾Java设计模式之状态模式

    原文地址 折腾Java设计模式之状态模式 状态模式 在状态模式(State Pattern)中,类的行为是基于它的状态改变的.这种类型的设计模式属于行为型模式.在状态模式中,我们创建表示各种状态的对象 ...

  4. 折腾Java设计模式之模板方法模式

    博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...

  5. 折腾Java设计模式之访问者模式

    博客原文地址:折腾Java设计模式之访问者模式 访问者模式 Represent an operation to be performed on the elements of an object st ...

  6. 折腾Java设计模式之命令模式

    博客原文地址 折腾Java设计模式之命令模式 命令模式 wiki上的描述 Encapsulate a request as an object, thereby allowing for the pa ...

  7. 折腾Java设计模式之解释器模

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

  8. JAVA设计模式之解释器模式

    在阎宏博士的<JAVA与模式>一书中开头是这样描述解释器(Interpreter)模式的: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个 ...

  9. 折腾Java设计模式之迭代器模式

    迭代器模式 Provide a way to access the elements of an aggregate object sequentially without exposing its ...

随机推荐

  1. ELK 架构之 Logstash 和 Filebeat 安装配置

    上一篇:ELK 架构之 Elasticsearch 和 Kibana 安装配置 阅读目录: 1. 环境准备 2. 安装 Logstash 3. 配置 Logstash 4. Logstash 采集的日 ...

  2. linux学习(JDK,Tomcat,nginx)安装

    最近学习了在linux,在上面搭建了一个tomcat的服务器,后来又使用nginx进行反向代理了一下下,希望文章对初学者有所帮助. 1.安装JDK.(采用jdk的rpm包进行安装) 安装jdk之前需要 ...

  3. 战争热诚的python全栈开发之路

    从学习python开始,一直是自己摸索,但是时间不等人啊,所以自己为了节省时间,决定报个班系统学习,下面整理的文章都是自己学习后,认为重要的需要弄懂的知识点,做出链接,一方面是为了自己找的话方便,一方 ...

  4. awk 手册

    1. 前言 有关本手册 : 这是一本awk学习指引, 其重点着重于 : l        awk 适于解决哪些问题 ? l        awk 常见的解题模式为何 ? 为使读者快速掌握awk解题的模 ...

  5. 2.Spring构建REST Web Service

    上篇文章我们已经对Spring 已经有了一个初步的认识,接下来本篇文章我们将继续一起在官网学习新技术. 原文地址:https://spring.io/guides/gs/rest-service/ 本 ...

  6. 基于开源 Openfire 聊天服务器 - 开发Openfire聊天记录插件

    原文:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 随笔-150  评论- ...

  7. Python集合set

    集合 set 集合是无序的 集合的值是唯一的 求两个集合的关系: list1 = [1,4,5,7,3,6,7,9] list2 = set([2,6,0,66,22,8,4]) list3 = se ...

  8. IZT复杂电磁环境记录回放和模拟系统

    结合实验室复杂电磁环境特性与模拟研究需求,实现对复杂多变的电磁环境录制.分析.重构和模拟,记录回放系统应具备如下几项能力: 1.电磁环境信号记录能力:能够实现对9KHz-18GHz频带范围内射频信号的 ...

  9. Java 11 新功能来了!

    关键时刻,第一时间送达! 目前 Oracle 已经发布了 Java Development Kit 10,下个版本 JDK 11 也即将发布.本文介绍 Java 11 的新功能. 根据Oracle新出 ...

  10. shell脚本添加实例化参数

    通过shell脚本给GMP系统添加一个环境变量参数dateSwitchTimeInterval 1. insert.sh #!/bin/sh . ~/apphome/aic_export.sh #连接 ...