解释器模式

解释器模式,给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。

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

正则表达式就是解释器的一种应用,解释器为正则表达式定义了一个文法,如何表示一个特定的正则表达式,以及如何解释这个正则表达式。

抽象表达式

抽象表达式,声明一个抽象的解释操作,这个接口为抽象语法树中所有的节点所共享。

public abstract class AbstractExpression {public abstract void interpret(Context context);
}

终结符表达式

终结符表达式,实现与文法中的终结符相关联的解释操作。实现抽象表达式中所要求的接口,主要是一个interpret()方法。文法中每一个终结符都有一个具体终结表达式与之相对应。

public class TerminalExpression extends AbstractExpression {public void interpret(Context context) {System.out.println("终端解释器");}
}

非终结符表达式

非终结符表达式,为文法中的非终结符实现解释操作。对文法中每一条规则R1、R2……RN都需要一个具体的非终结符表达式类。通过实现抽象表达式的interpret()方法实现解释操作。解释操作以递归方式调用上面所提到的R1、R2、RN中各个符号的实例变量。

public class NonterminalExpression extends AbstractExpression {public void interpret(Context context) {System.out.println("非终端解释器");}
}

Context

包含解释器之外的一些全局信息。

public class Context {private String input;private String output;public String getInput() {return input;}public void setInput(String input) {this.input = input;}public String getOutput() {return output;}public void setOutput(String output) {this.output = output;}
}

客户端

客户端代码,构建表示该文法定义的语言中一个特定的句子的抽象语法树。调用解释操作。

public class Client {public static void main(String[] args) {Context context = new Context();List<AbstractExpression> list = new ArrayList<AbstractExpression>();list.add(new TerminalExpression());list.add(new NonterminalExpression());list.add(new TerminalExpression());list.add(new TerminalExpression());for (AbstractExpression exp : list) {exp.interpret(context);}}
}

解释器模式好处

当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使用解释器模式。

解释器模式,可以很容易地改变和扩展文法,因为该模式使用类来表示文法规则,你可使用继承来改变或扩展该文法。也比较容易实现文法,因为定义抽象语法树中各个节点的类的实现大体类似,这些类都易于直接编写。

解释器模式的不足,解释器模式为文法中的每一条规则至少定义了一个类,因此包含许多规则的文法可能难以管理和维护。建议当文法非常复杂时,使用其他的技术如语法分析程序或编译器生成器来处理。

音乐解释器

规则:
O表示音阶 O1表示低音阶 O2表示中音阶 O3表示高音阶
P表示休止符,'C D E F G A B’表示“Do-Re-Mi-Fa-So-La-Ti”
音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25表示四分之一拍,以此类推
注意:所有的字母和数字都要用半角空格分开,例如上海滩歌曲的第一句,“浪奔”,可以写成“O 2 E 0.5 G 0.5 A 3”,表示中音开始,演奏的是 mi so la。

演奏内容类

public class PlayContext {// 演奏文本private String playText;public String getPlayText() {return playText;}public void setPlayText(String text) {this.playText = text;}}

表达式类

public abstract class Expression {// 解释器public void interpret(PlayContext context) {if(context.getPlayText().length()==0) {return;} else {// 此方法用于将当前的演奏文本第一条命令获得命令字母和其参数值。// 例如“O 3 E 0.5 G 0.5 A 3”,则playKey为O,而playValue=3String playKey = context.getPlayText().substring(0,1);context.setPlayText(context.getPlayText().substring(2));double playValue = Double.parseDouble(context.getPlayText().substring(0,context.getPlayText().indexOf(" ")));// 获得playKey和playValue后将其从演奏文本中移除。// 例如“O 3 E 0.5 G 0.5 A 3”变成了“E 0.5 G 0.5 A 3”context.setPlayText(context.getPlayText().substring(context.getPlayText().indexOf(" ")+1));// 抽象方法“执行”,不同的文法子类,有不同的执行处理excute(playKey, playValue);}}// 执行public abstract void excute(String key,double value);
}

音符类(TerminalExpression)

public class Note extends Expression {@Overridepublic void excute(String key, double value) {String note = "";switch (key) {case "C":note = "1";break; // 表示如果获得的key是C则演奏1(do),如果是D则演奏2(Re)case "D":note = "2";break;case "E":note = "3";break;case "F":note = "4";break;case "G":note = "5";break;case "A":note = "6";break;case "B":note = "7";break;}System.out.print(note+" ");}}

音阶类(TerminalExpression)

public class Scale extends Expression {@Overridepublic void excute(String key, double value) {String scale = "";switch ((int)value) {case 1:scale = "低音";break; // 表示如果获得的key是O并且value是1则演奏低音,2则是中音,3则是高音case 2:scale = "中音";break;case 3:scale = "高音";break;}System.out.print(scale+" ");}}

音速类(TerminalExpression)

public class Speed extends Expression {@Overridepublic void excute(String key, double value) {String speed = "";if (value < 500) {speed = "快速";} else if (value >= 1000) {speed = "慢速";} else {speed = "中速";}System.out.print(speed + " ");}
}

客户端

/***规则:* O表示音阶 O1表示低音阶 O2表示中音阶 O3表示高音阶* P表示休止符,'C D E F G A B'表示“Do-Re-Mi-Fa-So-La-Ti”* 音符长度1表示一拍,2表示二拍,0.5表示半拍,0.25表示四分之一拍,以此类推* 注意:所有的字母和数字都要用半角空格分开,例如上海滩歌曲的第一句,“浪奔”,可以写成“O 2 E 0.5 G 0.5 A 3”,表示中音开始,演奏的是 mi so la。* */
public class Client {public static void main(String[] args) {PlayContext context = new PlayContext();// 音乐-上海滩System.out.println("上海滩:");context.setPlayText("T 500 O 2 E 0.5 G 0.5 A 3 E 0.5 G 0.5 D 3 E 0.5 G 0.5 A 0.5 O 3 C 1 O 2 A 0.5 G 1 C 0.5 E 0.5 D 3 ");Expression expression = null;try {while(context.getPlayText().length()>0) {String str = context.getPlayText().substring(0,1);switch(str) {case "O":expression = new Scale(); break;// 当首字段是O时,则表达式实例化为音阶case "T":expression = new Speed(); break;case "C":case "D":case "E":case "F":case "G":case "A":case "B":case "P":expression = new Note();break;  // 当首字母是CDEFGAB,以及休止符P时,则实例化音符}expression.interpret(context);}} catch (Exception e) {System.out.println(e.getMessage());}}
}

注:本文内容源自程杰的《大话设计模式》

大话设计模式——解释器模式相关推荐

  1. 大话设计模式:解释器模式

    一.什么是解释器模式 定义一个语言,定义一个解析器,解析器解释语言 某种繁复的输入可有一定规律抽象为行为,定义语言,使用解释器将这些语言转换为行为,解释器模式提供了评估语言的语法或表达式的方式.这种模 ...

  2. linkin大话设计模式--常用模式总结

    linkin大话设计模式--常用模式总结 一,常用设计模式定义 Abstract Factory(抽象工厂模式):提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. Adapter( ...

  3. Python设计模式-解释器模式

    Python设计模式-解释器模式 代码基于3.5.2,代码如下; #coding:utf-8 #解释器模式class PlayContext():play_text = Noneclass Expre ...

  4. linkin大话设计模式--桥接模式

    linkin大话设计模式--桥接模式 桥接模式是一种结构化模式,他主要应对的是:由于实际的需要,某个类具有2个或者2个以上维度的变化,如果只是使用继承将无法实现功能,或者会使得设计变得相当的臃肿.我们 ...

  5. linkin大话设计模式--模板方法模式

    linkin大话设计模式--模板方法模式 准备一个抽象类,将部分逻辑以具体方法的形式实现,然后申明一些抽象方法来迫使子类实现剩余的逻辑.不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不 ...

  6. 设计模式 | 解释器模式及典型应用

    微信原文:设计模式 | 解释器模式及典型应用 博客原文:设计模式 | 解释器模式及典型应用 本文主要介绍解释器模式,在日常开发中,解释器模式的使用频率比较低 解释器模式 解释器模式(Interpret ...

  7. C++设计模式-解释器模式

    目录 基本概念 代码与实例 基本概念 解释器模式(interpreter):给定一个语言,定义他的文法的一种表示,并定义一个解释器,这个解释器应该使用该表示来解释语言中的句子. 如果一种特定类型的问题 ...

  8. 深入浅出设计模式——解释器模式(Interpreter Pattern)

    模式动机 如果在系统中某一特定类型的问题发生的频率很高,此时可以考虑将这些问题的实例表述为一个语言中的句子,因此可以构建一个解释器,该解释器通过解释这些句子来解决这些问题. 解释器模式描述了如何构成一 ...

  9. PHP设计模式——解释器模式

    声明:本系列博客参考资料<大话设计模式>,作者程杰. 解释器模式:Given a language, define arepresentation for its grammar alon ...

  10. 大话设计模式—命令模式

    命令模式(Command Pattern)是一种数据驱动的设计模式,它属于行为型模式.请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该 ...

最新文章

  1. django初探-创建简单的博客系统(一)
  2. 国家“十三五”重点出版规划获批
  3. JVM性能调优监控工具专题二:VisualVM基本篇之监控JVM内存,CPU,线程
  4. Hibernate执行原理总结
  5. 如何在 MacOS 环境下搭建 SVN 服务端环境
  6. 网络爬虫--8.编码趣闻
  7. ESXi安全引导如何提升vSphere安全性?
  8. 带你自学Python系列(九):input函数和程序循环四维导图导图
  9. it书籍分享免费下载
  10. 通达信版弘历软件指标_背离王 通达信副图源码 为弘历软件破释公式
  11. 微信小程序下拉刷新,上拉加载
  12. Hbuilder里运行到手机或模拟器手机和电脑配置
  13. 用python计算工资工资_薪资计算-Python,薪水,python
  14. Unity3d优化总结2
  15. linux学习笔记-第三课-ls,cd,alias,PASH,目录结构,快捷键
  16. GaussDB_T 单机版轻量安装
  17. 数据分析--数据合并
  18. 写给人类的机器学习 六、最好的机器学习资源
  19. javax.validation.constraints.NotNull找不到
  20. GBoost 和 xGBoost

热门文章

  1. 编程猫海龟编辑器 附使用教程
  2. 推荐5款常用编程文本编辑器
  3. 激光雷达考试基础知识
  4. 微信公众号、订阅号、服务号区别
  5. 阿里云域名如何拍卖?
  6. 解构网约车界“拼多多”:花小猪背后的商业逻辑和价值空间
  7. 2020年阴历二月二十六 投资理财~读万科财报有感
  8. python因子分析_python中的因子分析简介
  9. 小学数学题生成器java_JAVA小学四则运算生成器(聂适涵,邱品)
  10. vue 路由守卫 解析