解释器模式

简介

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. C++多重继承虚表的内存分布

    接前面虚表的内存分布,今天重点看多重继承的虚表内存分布,简单的说,继承几个类便有几个虚表,如下代码 class Drive : public Base1, public Base2, public B ...

  2. Java学习----不变的常量

    byte: -128~+127 short int:129 long float:1.5f  (1.5被系统默认为double) double:4.5d char:'s'  '1' boolean:t ...

  3. Yii2的相关学习记录,下载Yii2(一)

    原先学习过Yii1的相关知识,虽然也是半懂不懂的,但稍微的结构是了解的.现在利用晚上的时间学习下Yii2的使用,打算建一个后台管理系统,这里记录下,以免自己以后忘记. 目前已看一部分Yii2的权威指南 ...

  4. Python新手学习基础之函数-lambda函数

    lambda函数 在Python里除了用def定义函数外,还有一种匿名函数,也就是标题所示的lambda函数,它是指一类无需定义标识符(函数名)的函数或子程序. lambda函数的使用语法如下: la ...

  5. bzoj2067: [Poi2004]SZN

    Description String-Toys joint-stock 公司需要你帮他们解决一个问题. 他们想制造一个没有环的连通图模型. 每个图都是由一些顶点和特定数量的边构成. 每个顶点都可以连向 ...

  6. IDE 常用快捷键记录

    一:Eclipse (1)删除当前行:Ctrl+D (2)最大化当前编辑窗口:Ctrl+m (3)关闭当前编辑器窗口:Ctrl+F4/Ctrl+w (4)导入依赖包:Ctrl+Shift+o 二:Ne ...

  7. U盘安装,FTP安装CENTOS--错误信息:Unable to read package metadata.This may be due to a missing repodata directory.

    考察repodata下的repomd.xml里的文件和同一目录下的那些文件是不是一一对应的.主要看有没后缀.如果不一致,则要用XML里的文件后缀加上去. 弄了我好多次. http://renzhenx ...

  8. sort_buffer_size:

    sort_buffer_size: 每个session 必须执行一个排序 分配一个 这个大小的buffer. sort_buffer_size 不特定的对于任何存储引擎适用于一般的优化方式. sort ...

  9. cursor pin S wait on X

    cursor pin S wait on X: 这是10.2版本提出的mutex(互斥)机制用来解决library cache bin latch争夺问题引入的新事件,是否使用这种机制受到隐含参数_k ...

  10. 反汇编动态追踪工具Ollydbg. ALD,ddd,dbg,edb...

    Ollydbg 通常称作OD,是反汇编工作的常用工具,吾爱破解OD附带了118脱壳脚本和各种插件,功能非常强大,基本上不需要再附加安装其它插件了. 对OD的窗口签名进行了更改,从而避免被针对性检测 修 ...