解释器模式

简介

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. Thinkphp---练习:数据的增删改查

    利用ThinkPHP连接数据库的增删改查的例题:用到的数据库表名Info表,Nation表 数据显示页面:MainController.class.php中的方法(增删改查全包括--function ...

  2. MLlib-分类与回归

    MLlib支持二分类,多酚类和回归分析的多种方法,具体如下: 问题类别 支持方法 二分类 线性支持向量机, 逻辑回归,决策树,朴素贝叶斯 多分类 决策树,朴素贝叶斯 回归 线性最小二乘,Lasso,r ...

  3. 触摸事件 - UIControlEvents

    首先,UIControlEvents有这个几种: UIControlEventTouchDown           = 1 <<  0,      // on all touch dow ...

  4. Egret 文本处理

    常规处理: private createGameScene():void { var shp = new egret.Shape(); shp.graphics.beginFill(0xff0000, ...

  5. Ant快速入门(一)-----Ant介绍

    Ant是一种基于Java的生成工具.从作用上来看,它类似于C编程(UNIX平台上使用比较多)的Make工具,C/C++项目经常使用Make工具来管理整个项目的编译,生成 Make使用Shell命令来定 ...

  6. 用c语言程序对显存进行操作

    一.基础研究 我们之前研究过变量.数组.函数和指针,他们都可以看作是内存中存储的一段数据,当程序需要用到它们时,会通过它们的地址找到它们并进行调用,只是调用的用途不同而已:变量和数组元素是作为常量来处 ...

  7. 转:PHP教程之PHP调用session_start后页面始终加载的问题研究

    今天群里有朋友说他的遇到一个有趣的问题: 一个PHP页面的执行时间比较长(15秒左右),而只要这个页面没有执行完毕,其他的页面访问都是长时间加载状态,只有那个页面执行完毕了,剩下的页面才能打开. 这是 ...

  8. Minimum Depth of Binary Tree ——LeetCode

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  9. Merge Two Sorted Lists—LeetCode

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

  10. throw new DataException("检查服务器是否存在失败:" + ex);

    try            { }            catch (Exception ex)            {                LogHelper.Error(" ...