【设计模式 - 15】之解释器模式(Interpreter)
1、模式简介
解释器模式允许我们自定义一种语言,并定义一个这种语言的解释器,这个解释器用来解释语言中的句子。由于这种模式主要用于编译器的编写,因此在日常应用中不是很常用。
如果一种特定类型的问题发生频率足够高,那么可能就值得将该问题的各个实例表述为一种简单语言中的一个句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
解释器模式的优点:
- 可扩展性比较好,灵活;
- 增加了新的解释表达式的方式;
- 易于实现简单文法。
解释器模式的缺点:
- 可利用场景比较少;
- 对于复杂的文法比较难维护;
- 解释器模式会引起类膨胀;
- 解释器模式采用递归调用方法。
解释器模式的使用场景:
- 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树;
- 一些重复出现的问题可以用一种简单的语言来进行表达;
- 一个简单语法需要解释的场景。
2、案例
在本例中我们定义一个解释器来解决日常的算数问题,如:(a + b) / (a - b + 6) * a。具体代码如下:
在解释器模式中,每个操作或参数都可以被抽象成一个表达式,因此我们首先定义一个表达式抽象类Expression,代码如下:
public abstract class Expression {
protected String key;
public String getKey() {
return key;
}
public abstract Expression interpret(Context context);
}
变量表达式VariableExpression中的代码:
public class VariableExpression extends Expression {
private Integer value;
public VariableExpression(String key, Integer value) {
super.key = key;
this.value = value;
}
public Integer getValue() {
return value;
}
@Override
public Expression interpret(Context context) {
context.addVariable(super.key, value);
return this;
}
}
加减乘除表达式的代码,这里以除法表达式DivideExpression中的代码为例:
public class DivideExpression extends Expression {
private String resultExpressionKey;
private Expression leftExpression;
private Expression rightExpression;
public DivideExpression(String resultExpressionKey, Expression leftExpression, Expression rightExpression) {
this.resultExpressionKey = resultExpressionKey;
this.leftExpression = leftExpression;
this.rightExpression = rightExpression;
}
@Override
public Expression interpret(Context context) {
Integer rightVariableValue = ((VariableExpression) rightExpression).getValue();
if (rightVariableValue != 0) {
return new VariableExpression(resultExpressionKey,
((VariableExpression) leftExpression).getValue() / rightVariableValue);
}
return null;
}
}
测试类Test中的代码如下:
/**
* 计算:(a + b) / (a - b + 6) * a
*/
public class Test {
public static void main(String[] args) {
// 上下文对象
Context context = new Context();
// 向上下文对象中添加变量
VariableExpression a = (VariableExpression) new VariableExpression("a", 11).interpret(context);
VariableExpression b = (VariableExpression) new VariableExpression("b", 10).interpret(context);
VariableExpression c = new VariableExpression("c", 6); // 开始计算
Expression tmpResult1 = new AddExpression("tmp1", a, b).interpret(context);
Expression tmpResult2 = new MinusExpression("tmp2", a, b).interpret(context);
Expression tmpResult3 = new AddExpression("tmp3", tmpResult2, c).interpret(context);
Expression tmpResult4 = new DivideExpression("tmp4", tmpResult1, tmpResult3).interpret(context);
Expression tmpResult5 = new MultiplyExpression("tmp5", tmpResult4, a).interpret(context); // 打印结果
System.out.println("结果是:" + ((VariableExpression) tmpResult5).getValue());
}
}
运行结果如下图所示:
最后贴出解释器模式在GitHub中的代码地址:【GitHub - Interpreter】。
【设计模式 - 15】之解释器模式(Interpreter)的更多相关文章
- 《JAVA设计模式》之解释器模式(Interpreter)
在阎宏博士的<JAVA与模式>一书中开头是这样描述解释器(Interpreter)模式的: 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个 ...
- 乐在其中设计模式(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进阶篇设计模式之九----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
- Java设计模式之九 ----- 解释器模式和迭代器模式
前言 在上一篇中我们学习了行为型模式的责任链模式(Chain of Responsibility Pattern)和命令模式(Command Pattern).本篇则来学习下行为型模式的两个模式, 解 ...
- 大话设计模式Python实现-解释器模式
解释器模式(Interpreter Pattern):给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 下面是一个解释器模式的demo: #!/usr/ ...
- 设计模式之GOF23解释器模式
解释器模式Interpreter -是一种不常用的设计模式 -用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的编译器和解释器设计 -当我们需要开发一种新的语言时,可以考虑使用解释器 ...
- [设计模式] 15 解释器模式 Interpreter
在GOF的<设计模式:可复用面向对象软件的基础>一书中对解释器模式是这样说的:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子.如果一种特定类 ...
随机推荐
- grub2 使用memdisk工具 启动任意iso
root@zhanghua-Inspiron-:/home/zhanghua# df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/sda6 60G 12G 46G 21% / none ...
- ibatis面试笔记
ibatis是在结果集与实体类之间进行映射hibernate是在数据库与实体类之间进行映射Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序 ...
- Xcode-程序开发设计-01UIKit 框架
CGRect中的前缀:CoreGraphics.frameworksUIView中的前缀:User InterFace 属于UIKit的框架NS前缀,NS是NextStep 对象方法:辞去第1响应者- ...
- Lambda表达式, 可以让我们的代码更优雅.
在C#中, 适当地使用Lambda表达式, 可以让我们的代码更优雅. 通过lambda表达式, 我们可以很方便地创建一个delegate: 下面两个语句是等价的 Code highlighting p ...
- BZOJ 3083 遥远的国度 树链剖分
3083: 遥远的国度 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 797 Solved: 181[Submit][Status] Descrip ...
- 【技术贴】解决支付宝充值信用卡还款跳转到网上银行报错Error 404 - Not Found
声明 : 本文在 GFDL 1.2 下发布,本文出处光大银行信用卡 http://bbs.090989.com/forum-186-1.html http://androidgao.blogspot ...
- C语言中.h和.c文件解析
整理自C语言中.h和.c文件解析(很精彩) Part.1(林锐<高质量C/C++编程>) 通过头文件来调用库功能.在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的 ...
- mysql 字段存储类型
摘自:http://zuo.ai.xiao.blog.163.com/blog/static/6079155320121293750732/ 1.数字类型 ...
- java中如何实现全局变量
有时一个项目中会多处涉及到路径,当你把这个项目移植到别的电脑上时就要一一修改这些路径,过程十分繁琐,所以一个全局变量在这时是必不可少的. 遗憾的是java等oo语言并没有全局变量,这怎么办呢?下面介绍 ...
- SPOJ-COT-Count on a tree(树上路径第K小,可持久化线段树)
题意: 求树上A,B两点路径上第K小的数 分析: 同样是可持久化线段树,只是这一次我们用它来维护树上的信息. 我们之前已经知道,可持久化线段树实际上是维护的一个前缀和,而前缀和不一定要出现在一个线性表 ...