解释器模式

简介

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

Interpreter Expression 解释器模式 MD的更多相关文章

  1. Interpreter Expression 解释器模式

    简介 Interpreter模式也叫解释器模式,是由GoF提出的23种设计模式中的一种.Interpreter是行为模式之一,它是一种特殊的设计模式,它建立一个解释器,对于特定的计算机程序设计语言,用 ...

  2. 解释器模式(Interpreter)

    解释器模式(Interpreter)解释器模式是我们暂时的最后一讲,一般主要应用在OOP开发中的编译器的开发中,所以适用面比较窄. Context类是一个上下文环境类,Plus和Minus分别是用来计 ...

  3. Atitit.linq java的原理与实现 解释器模式

    Atitit.linq java的原理与实现 解释器模式 1. Linq  from  where 的实现1 2. Where expr 的实现1 3. Attilax的一点变化2 4. 解释器模式的 ...

  4. 解释器模式(Interpreter、Context、Expression)

    (给定一门语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.) 解释器模式的定义是一种按照规定语法进行解析的方案,在现在项目中使用的比较少,其定义如下: Given ...

  5. [工作中的设计模式]解释器模式模式Interpreter

    一.模式解析 解释器模式是类的行为模式.给定一个语言之后,解释器模式可以定义出其文法的一种表示,并同时提供一个解释器.客户端可以使用这个解释器来解释这个语言中的句子. 以上是解释器模式的类图,事实上我 ...

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

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

  7. 【设计模式 - 15】之解释器模式(Interpreter)

    1      模式简介 解释器模式允许我们自定义一种语言,并定义一个这种语言的解释器,这个解释器用来解释语言中的句子.由于这种模式主要用于编译器的编写,因此在日常应用中不是很常用. 如果一种特定类型的 ...

  8. 面向对象设计模式之Interpreter解释器模式(行为型)

    动机:在软件构建过程中 ,如果某一特定领域的问题比较复杂,类似的模式不断重复出现,如果使用普通的编程方式来实现将面临非常频繁的变化.在这种情况下,将特定领域的问题表达为某种语法规则的句子,然后构建一个 ...

  9. 第19章 解释器模式(Interpreter Pattern)

    原文 第19章 解释器模式(Interpreter Pattern) 解释器模式 导读:解释器模式,平常用的比较的少,所以在写这个模式之前在博客园搜索了一番,看完之后那叫一个头大.篇幅很长,我鼓足了劲 ...

随机推荐

  1. Laravel框架初学一路由(基本路由)

    基本路由 Laravel最基本的路由:接收一个URI和Closure闭包函数 ,提供了定义路由的一种非常简单且富有表达力的方式 Route::get("foo", function ...

  2. HDU - 1022 Train Problem I STL 压栈

    Train Problem I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  3. Entity Framework Core介绍(1)

    介绍 Entity Framework (EF) Core 是轻量化.可扩展和跨平台版的常用 Entity Framework 数据访问技术. EF Core 可用作对象关系映射程序 (O/RM),以 ...

  4. 转 Java高级程序员面试题

    1.你认为项目中最重要的过程是那些? 分析.设计阶段  尽量找出进度的优先级 2.如果给你一个4-6人的team,怎么分配? 挑选一技术过硬的人作为我的替补.其它人平均分配任务,每周进行全面的任务分配 ...

  5. ASP.NET MVC 提高运行速度的几种性能优化方法

    主要介绍ASP.NETMVC 应用提速的六种方法,因为没有人喜欢等待,所以介绍几种常用的优化方法. 大家可能会遇到排队等待,遇到红灯要等待,开个网页要等待,等等等. 理所当然,没有人喜欢等待网页慢吞吞 ...

  6. 【SQL】185. Department Top Three Salaries

    The Employee table holds all employees. Every employee has an Id, and there is also a column for the ...

  7. JSTL介绍

    JSTL介绍 一.介绍 JSP标准标签库(JSTL)是一个JSP标签集合,它封装了JSP应用的通用核心功能. JSTL支持通用的.结构化的任务,比如迭代,条件判断,XML文档操作,国际化标签,SQL标 ...

  8. 【贪心】【堆】Gym - 101775B - Scapegoat

    题意:有n个事件,每个事件有一个严重程度,m个人(m>=n),你要让m个人去背锅,每个人只能背一个事件的锅,但是一个事件可以由很多人背.让你使得这m个人所承受的严重程度的方差最小化. 考虑一开始 ...

  9. POJ 2356 Find a multiple 抽屉原理

    从POJ 2356来体会抽屉原理的妙用= =! 题意: 给你一个n,然后给你n个数,让你输出一个数或者多个数,让这些数的和能够组成n: 先输出一个数,代表有多少个数的和,然后再输出这些数: 题解: 首 ...

  10. cocos2dx 3.0 中文 iconv 转换函数

    //#include <string> #pragma once #include "cocos2d.h"; #include "iconv\include\ ...