解释器模式

简介

Interpreter模式也叫解释器模式,是行为模式之一,它是一种特殊的设计模式,它建立一个解释器,对于特定的计算机程序设计语言,用来解释预先定义的文法。

应用环境:

  • 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。而且当文法简单、效率不是关键问题的时候效果最好。
  • 当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树,可以使用解释器模式。

角色:

  • 抽象表达式角色(AbstractExpression): 声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的
  • 终结符表达式角色(TerminalExpression): 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符
  • 非终结符表达式角色(NonterminalExpression): 文法中的每条规则对应于一个非终结表达式,非终结表达式根据逻辑的复杂程度而增加,原则上每个文法规则都对应一个非终结符表达式
  • 环境角色(Context): 包含解释器之外的一些全局信息

优点:

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

缺点:

  • 解释器模式会引起【类膨胀】,每个语法都要产生一个非终结符表达式,语法规则比较复杂时,可能产生大量的类文件,难以维护
  • 解释器模式采用【递归调用】方法,它导致调试非常复杂
  • 解释器由于使用了大量的循环和递归,所以当用于解析复杂、冗长的语法时,【效率】是难以忍受的

注意事项:

  • 尽量不要在重要模块中使用解释器模式,因为维护困难。在项目中,可以使用shell,JRuby,Groovy等脚本语言来代替解释器模式。

作用:用一组类代表某一规则

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

java.util.Pattern
java.text.Format

  

案例

环境角色

class Context {
private Map<String, Integer> valueMap = new HashMap<String, Integer>();
public void addValue(String key, int value) {
valueMap.put(key, value);
}
public int getValue(String key) {
return valueMap.get(key);
}
}

  

抽象表达式角色

声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的

abstract class AbstractExpression {
public abstract int interpreter(Context context);
}

  

终结符表达式角色

实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符
Terminal 终结符,末期的,晚期的。终结符是语言中用到的基本元素,一般不能再被分解

class TerminalExpression extends AbstractExpression {
private int i;
public TerminalExpression(int i) {
this.i = i;
}
@Override
public int interpreter(Context context) {//不进行任何操作
return i;
}
}

  

非终结符表达式角色

文法中的每条规则对应于一个非终结表达式,非终结表达式根据逻辑的复杂程度而增加

加法操作

class AddNTExpression extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
public AddNTExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
return left.interpreter(context) + right.interpreter(context);
}
}

  

减法操作

class SubtractNTExpression extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
public SubtractNTExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
return left.interpreter(context) - right.interpreter(context);
}
}

  

乘法操作

class MultiplyNTExpression extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
public MultiplyNTExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
return left.interpreter(context) * right.interpreter(context);
}
}

  

除法操作

class DivisionNTExpression extends AbstractExpression {
private AbstractExpression left;
private AbstractExpression right;
public DivisionNTExpression(AbstractExpression left, AbstractExpression right) {
this.left = left;
this.right = right;
}
@Override
public int interpreter(Context context) {
int value = right.interpreter(context);
if (value != 0) return left.interpreter(context) / value;
return -1111;
}
}

  

使用演示

public class Test {
public static void main(String[] args) {
//计算(7*8)/(7-8+2)的值
Context context = new Context();
context.addValue("a", 7);
context.addValue("b", 8);
context.addValue("c", 2);

AbstractExpression multiplyValue = new MultiplyNTExpression(new TerminalExpression(context.getValue("a")), new TerminalExpression(context.getValue("b")));//计算a*b
AbstractExpression subtractValue = new SubtractNTExpression(new TerminalExpression(context.getValue("a")), new TerminalExpression(context.getValue("b")));//计算a-b

AbstractExpression addValue = new AddNTExpression(subtractValue, new TerminalExpression(context.getValue("c")));//计算(a-b)+c

AbstractExpression divisionValue = new DivisionNTExpression(multiplyValue, addValue);//计算(a*b)/(a-b+c)

System.out.println(divisionValue.interpreter(context));
}
}

  

案例二

创建一个表达式接口

public interface Expression { //表达式接口
boolean interpret(String context); //解释指定的内容
}

  

创建实现了上述接口的实体类

public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data){
this.data = data;
}
@Override
public boolean interpret(String context) {
if(context.contains(data)){ //包含
return true;
}
return false;
}
}
public class OrExpression implements Expression {

private Expression expr1 = null;
private Expression expr2 = null;

public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context); //两个表达式是否有一个能解释指定内容
}
}
public class AndExpression implements Expression {

private Expression expr1 = null;
private Expression expr2 = null;

public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}

@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context); //两个表达式是否都能解释指定内容
}
}

  

测试

public class Test {
public static void main(String[] args) {
//使用 Expression 类来创建规则,并解析它们。
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
Expression or = new OrExpression(robert, john);
System.out.println(or.interpret("John")); //true

Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
Expression and = new AndExpression(julie, married);
System.out.println(and.interpret("Married Julie")); //true
}
}

  

2016-08-24

AS 断点调试 debug的更多相关文章

  1. Visual Studio 2015 MFC之Button颜色变化-断点调试(Debug)

    软件开发,对自己的程序进行调试很重要,本次文章在上一边随笔的基础上,介绍一下Button控件做显示灯的用法,Button控件的添加和变量设置等可以参考下面的的链接:Visaul Studio 2015 ...

  2. Spring Boot项目使用Eclipse进行断点调试Debug

    1.在命令行下定位到项目根目录,启动Spring Boot项目,命令如下: java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=80 ...

  3. react native断点调试--Debug React-Native with VSCode

    .babelrc { "presets": [ "react-native" ], "sourceMaps": true } Many Ja ...

  4. Tomcatd断点调试Debug

    ideaDebug设置

  5. debug断点调试

    debug断点调试  1,虫子启动2,F6   执行断点的下一步,下一个语句     F5    进入方法     F8   执行到结束    查看表达式的值:选中查看的表达式,接着按   ctrl ...

  6. myeclipse如何设置或关闭断点调试自动跳入debug模式

    遇到了很坑的问题,在myeclipse(eclipse应该也一样)开发过程中,打了断点调试,最初时候会弹出一个弹出框,让你选择是否进入debug模式,结果一不小心点了一个记住选择,然后选择了yes,结 ...

  7. Intellij IDEA 2017 debug断点调试技巧与总结详解篇

    转载自csdn----------------------------------------------------------------------https://blog.csdn.net/q ...

  8. myeclipse下对tomcat项目进行debug断点调试

    对于eclipse或myeclipse调试J2SE项目或小应用进行断点调试,大家都不陌生,只要设置断点,debug运行就OK了.但是如果是web项目,而项目是在容器中运行的,比如tomcat,resi ...

  9. (转)Intellij IDEA 2017 debug断点调试技巧与总结详解篇

    背景:详细介绍idea的debug调试过程 Intellij IDEA 2017 debug断点调试技巧与总结详解篇

随机推荐

  1. [Head First设计模式笔记]----命令模式

    命令模式定义:将“请求”封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 类图: 适用设计方案举例:实现一种遥控器,该遥控器具有七个可编程的插槽(每个都可以指 ...

  2. 【POJ1753】Flip Game

    [题目大意] 有一个4x4规格的一个棋盘,现在有16个一面黑一面白的棋子分布在这个棋盘上. 翻转一个棋子能够使它以及它上下左右的四个棋子从黑变白,从白变黑. 现在问你至少要经过多少次操作才能够使得整个 ...

  3. wamp环境网站根目录更改

    1.修改wampserver的默认目录 安装好wampserver后,网站根目录默认为:安装目录\wamp\www,也就是wampserver安装目录下的www文件夹. 我们以更改为:D\www为例. ...

  4. Javascript中回调函数的学习笔记

    function a_b(kkis){ document.body.style.background ='red'; kkis(); } function fli(){ alert('######## ...

  5. 探究Android中Listview显示错乱问题

    问题 最近在项目中遇到过一个很棘手的问题,就是ListView在滑动后就莫名其妙的显示错乱,网上查阅资料后问题很容易的就解决了,但是对于问题产生的原因仍是一知半解,所以不甘心的我定下心来,狠读源码,终 ...

  6. Solr4.8.0源码分析(8)之Lucene的索引文件(1)

    Solr4.8.0源码分析(8)之Lucene的索引文件(1) 题记:最近有幸看到觉先大神的Lucene的博客,感觉自己之前学习的以及工作的太为肤浅,所以决定先跟随觉先大神的博客学习下Lucene的原 ...

  7. winform拖动无边框窗体

    这个无边框拖动船体,代码很少,却总是记不住,于是就在网上搜了这段代码,记录一下,省的再忘 using System; using System.Collections.Generic; using S ...

  8. 如何将github上的微信客户端类库能够通过composer工具下载

    我将自己开发的微信客户端类库放到了github上面去了. 然后我在我的项目里面添加了一个composer.json文件 内容如下 { "require": { "weix ...

  9. ionic中使用Cordova Uglify 压缩js与css

    参照:https://www.npmjs.com/package/cordova-uglify 安装:npm install cordova-uglify 安装完成之后,打开: hooks/uglif ...

  10. 软硬大比拼 硅胶、TPU和PC材质对比

    手机保护壳的材质有很多种,目前保护壳市场上最为常见的就是硅胶.TPU.PC材质了.那么我们不禁要问,PU.硅胶.PC三材质到底有哪些区别呢?普通消费者在购买保护壳的时候能否从外表就能看出保护壳材质?P ...