一、什么是解释器模式:

        解释器模式,就是定义语言的文法,并建立一个解释器来解释该语言中的句子,通过构建解释器,解决某一频繁发生的特定类型问题实例。

这里我们将语言理解成使用规定格式和语法的代码

解释器模式描述了如何构成一个简单的语言解释器,主要应用在使用面向对象语言开发的编译器中,它描述了如何为简单的语言定义一个文法,如何在该语言中表示一个句子,以及如何解释这些句子。

例如我们经常利用正则表达式检测某些字符串是否符合我们规定的格式。这里正则表达式就是解释器模式的应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。

解释器模式中除了能够使用文法规则来定义一个语言,还能通过使用抽象语法树来更加直观表示、更好地地表示一个语言的构成,每一颗抽象语法树对应一个语言实例。抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。

二、UML结构图:

  • AbstractExpression:抽象解释器,声明一个抽象的解释操作方法 interpret()。具体解释任务由它的各个实现类来完成,具体解释器分别由终结符解释器 TerminalExpression 和非终结符解释器 NonterminalExpression 完成。
  • TerminalExpression:终结符表达式,实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例,对应不同的终结符。终结符一般是文法中的运算单元,比如有一个简单的公式 R = R1 + R2,在里面 R1 和R2 就是终结符,解析 R1 和 R2 的解释器就是终结符表达式。
  • NonterminalExpression:非终结符表达式,文法中的每条规则对应于一个非终结符表达式,非终结符表达式一般是文法中的运算符或者其他关键字,比如公式 R = R1 + R2中,+就是非终结符,解析+的解释器就是一个非终结符表达式。非终结符表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式。
  • Context:环境类,包含解释器之外的一些全局信息,这个角色的任务一般是用来存放文法中各个终结符所对应的具体值,比如 R = R1 + R2,我们给 R1 赋值 100,给 R2 赋值 200。这些信息需要存放到环境角色中,很多情况下我们使用Map来充当环境角色就足够了。
  • 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、优点:

(1)解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。

(2)增加了新的解释表达式的方式。

(3)易于实现文法。

2、缺点:

(1)解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。

(2)效率低下,采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。

3、适用场景:

(1)有一个简单的语法规则,比如一个sql语句,如果我们需要根据sql语句进行rm转换,就可以使用解释器模式来对语句进行解释。

(2)一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-c*d,有时是a*b+c-d,等等,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。


设计模式系列文章:

Java设计模式之创建型:工厂模式详解(简单工厂+工厂方法+抽象工厂)

Java设计模式之创建型:建造者模式

Java设计模式之创建型:单例模式

Java设计模式之创建型:原型模式

Java设计模式之结构型:适配器模式

Java设计模式之结构型:装饰器模式

Java设计模式之结构型:代理模式

Java设计模式之结构型:桥接模式

Java设计模式之结构型:外观模式

Java设计模式之结构型:组合模式

Java设计模式之结构型:享元模式

Java设计模式之行为型:策略模式

Java设计模式之行为型:模板方法模式

Java设计模式之行为型:责任链模式

Java设计模式之行为型:观察者模式

Java设计模式之行为型:访问者模式

Java设计模式之行为型:中介者模式

Java设计模式之行为型:命令模式

Java设计模式之行为型:状态模式

Java设计模式之行为型:备忘录模式

Java设计模式之行为型:迭代器模式

Java设计模式之行为型:解释器模式


原博客链接:

设计模式读书笔记-----解释器模式_chenssy 的技术博客-CSDN博客

23种设计模式(14):解释器模式_三级小野怪的专栏-CSDN博客_解释器模式

Java设计模式之行为型:解释器模式相关推荐

  1. 【Java设计模式】简单学解释器模式——加减乘除

    目录 说明 实现方式 应用场景 其他链接 说明 行为型模式之一,其他还有命令模式.模板方法模式.访问者模式.观察者模式.中介者模式.备忘录模式.迭代器模式.状态模式.策略模式.职责链模式(责任链模式) ...

  2. JAVA设计模式(14) —行为型模板方法模式(Template Method)

    1 定义: 模板方法模式(Template Method) Define the skeleton of an algorithm in anoperation, deferring some ste ...

  3. Java设计模式之创建型-建造者模式 (Builder)

  4. Java设计模式(16)中介模式(Mediator模式)

    Mediator定义:用一个中介对象来封装一系列关于对象交互行为. 为何使用Mediator模式/中介模式 各个对象之间的交互操作非常多,每个对象的行为操作都依赖彼此对方,修改一个对象的行为,同时会涉 ...

  5. Java设计模式(1)工厂模式(Factory模式)

    工厂模式定义:提供创建对象的接口. 为何使用工厂模式 工厂模式是我们最常用的模式了,著名的Jive论坛,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因 ...

  6. Java设计模式(8)组合模式(Composite模式)

    Composite定义:将对象以树形结构组织起来,以达成"部分-整体" 的层次结构,使得客户端对单个对象和组合对象的使用具有一致性. Composite比较容易理解,想到Compo ...

  7. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  8. Java设计模式之行为型:访问者模式

    背景: 去医院看病时,医生会给你一个处方单要你去拿药,拿药我们可以分为两步走: (1)去柜台交钱,划价人员会根据处方单上的药进行划价,交钱. (2)去药房拿药,药房工作者同样根据处方单给你相对应的药. ...

  9. Java设计模式之行为型:状态模式

    背景: 介绍状态模式前,我们先看这样一个实例:公司力排万难终于获得某个酒店的系统开发项目,并且最终落到了你的头上.下图是他们系统的主要工作: 当第一眼看到这个系统时你就看出这是一个状态图,每个框都代表 ...

最新文章

  1. Sinew Ex深度发掘金融衍生品市场价值
  2. 以下用于数据存储领域的python第三方库是-Python3爬虫学习之MySQL数据库存储爬取的信息详解...
  3. MongoDB之Hadoop驱动介绍
  4. 阿里云有一群 “猪猪侠”
  5. 第103篇Python:Python爬虫系列之书籍爬取,细节拉满
  6. wincc怎么做数据库_关于WINCC通过PLCSIM来进行仿真中要怎么设置?
  7. ubuntu上安装CLucene
  8. 解决安装多个Xcode出现的PBXProjectWizardChooserWizard问题
  9. SQLServer2008 去除换行符
  10. Julia: 奇技淫巧......
  11. 【从零开始学架构-李运华】02|架构设计的历史背景
  12. 普林斯顿微积分读本篇六:求解微分问题
  13. 【图解算法使用C++】1.2 生活中的算法
  14. JAVA计算机毕业设计藏宝阁游戏交易系统Mybatis+系统+数据库+调试部署
  15. 两个分数化简比怎么化_两个分数的比化简怎么化急用
  16. Quick BI 数据大屏快速入门
  17. ubuntu机械盘写入cannot be copied because you do not have permissions to create it in the destination.
  18. Bolzano-Weierstrass 定理
  19. 慧算账V2.0版发布,互联网记账再升级
  20. Android 关于禁止应用截屏和录屏

热门文章

  1. webpack 语法
  2. 鲨鱼 抓包 oracle,ubuntu下网络抓包工具wireshark tcpdump的使用
  3. Tag recommendaion... 论文中的小例子,使用HOSVD算法推荐
  4. 超越GPT-3!NormFormer:归一化提高预训练、缓解梯度不匹配
  5. 从动力学角度看优化算法:一个更整体的视角
  6. 首届中国高校计算机大赛-人工智能创意赛启动,百度加盟全面赋能
  7. ICCV2017 论文解读:基于图像检索的行人重识别 | PaperDaily #13
  8. MyBatis框架:延迟加载策策略、一级缓存、二级缓存
  9. googlehelper手机版ios_二次元漫画控iOS苹果手机版下载v1.0.0下载|免费二次元漫画控iOS苹果手机版下载绿色版...
  10. 【Linux环境】Elasticsearch 启动停止服务的2类方法【及 java.nio.file.AccessDeniedException: xx/pid 问题解决】(含启停shell脚本)