简介

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

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

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

优点:
  • 解释器是一个简单语法分析工具,它最显著的优点就是【扩展性】,修改语法规则只要修改相应的【非终结符表达式】就可以了,若扩展语法,则只要增加【非终结符类】就可以了。
缺点:
  • 解释器模式会引起【类膨胀】,每个语法都要产生一个非终结符表达式,语法规则比较复杂时,可能产生大量的类文件,难以维护
  • 解释器模式采用【递归调用】方法,它导致调试非常复杂
  • 解释器由于使用了大量的循环和递归,所以当用于解析复杂、冗长的语法时,【效率】是难以忍受的
注意事项:
  • 尽量不要在重要模块中使用解释器模式,因为维护困难。在项目中,可以使用shell,JRuby,Groovy等脚本语言来代替解释器模式。

作用:用一组类代表某一规则
类图:四则运算
这个模式通常定义了一个语言的语法,然后解析相应语法的语句。
java.util.Pattern
java.text.Normalizer
java.text.Format

经典案例

public class Test2 {
    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));
    }
}

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);
    }
}

/**抽象表达式角色(AbstractExpression): 声明一个抽象的解释操作,这个接口为所有具体表达式角色都要实现的*/
abstract class AbstractExpression {
    public abstract int interpreter(Context context);
}

/**终结符表达式角色(TerminalExpression): 实现与文法中的元素相关联的解释操作,通常一个解释器模式中只有一个终结符表达式,但有多个实例对应不同的终结符*/
class TerminalExpression extends AbstractExpression {//Terminal 终结符,末期的,晚期的。终结符就是语言中用到的基本元素,一般不能再被分解
    private int i;
    public TerminalExpression(int i) {
        this.i = i;
    }
    @Override
    public int interpreter(Context context) {//不进行任何操作
        return i;
    }
}

/**非终结符表达式角色(NonterminalExpression): 文法中的每条规则对应于一个非终结表达式,非终结表达式根据逻辑的复杂程度而增加*/
class AddNTExpression extends AbstractExpression {//Nonterminal 非终结符号,非末端
    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 Context {
    private Map<Variable, Boolean> map = new HashMap<Variable, Boolean>();
    public void assign(Variable var, boolean value) {
        map.put(var, new Boolean(value));
    }
    public boolean lookup(Variable var) throws IllegalArgumentException {
        Boolean value = map.get(var);
        if (value == null) throw new IllegalArgumentException();
        return value.booleanValue();
    }
}

public abstract class Expression {
    /**以环境为准,本方法解释给定的任何一个表达式     */
    public abstract boolean interpret(Context ctx);
    @Override
    public int hashCode() {
        return this.toString().hashCode();
    }
}

class Constant extends Expression {
    private boolean value;
    public Constant(boolean value) {
        this.value = value;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof Constant) {
            return this.value == ((Constant) obj).value;
        }
        return false;
    }
    @Override
    public boolean interpret(Context ctx) {
        return value;
    }
    @Override
    public String toString() {
        return new Boolean(value).toString();
    }
}
class Variable extends Expression {
    private String name;
    public Variable(String name) {
        this.name = name;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof Variable) {
            return this.name.equals(((Variable) obj).name);
        }
        return false;
    }
    @Override
    public String toString() {
        return name;
    }
    @Override
    public boolean interpret(Context ctx) {
        return ctx.lookup(this);
    }
}

class And extends Expression {
    private Expression left, right;
    public And(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof And) {
            return left.equals(((And) obj).left) && right.equals(((And) obj).right);
        }
        return false;
    }
    @Override
    public boolean interpret(Context ctx) {
        return left.interpret(ctx) && right.interpret(ctx);
    }
    @Override
    public String toString() {
        return "(" + left.toString() + " AND " + right.toString() + ")";
    }
}
class Or extends Expression {
    private Expression left, right;
    public Or(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof Or) {
            return this.left.equals(((Or) obj).left) && this.right.equals(((Or) obj).right);
        }
        return false;
    }
    @Override
    public boolean interpret(Context ctx) {
        return left.interpret(ctx) || right.interpret(ctx);
    }
    @Override
    public String toString() {
        return "(" + left.toString() + " OR " + right.toString() + ")";
    }
}
class Not extends Expression {
    private Expression exp;
    public Not(Expression exp) {
        this.exp = exp;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj != null && obj instanceof Not) {
            return exp.equals(((Not) obj).exp);
        }
        return false;
    }
    @Override
    public boolean interpret(Context ctx) {
        return !exp.interpret(ctx);
    }
    @Override
    public String toString() {
        return "(Not " + exp.toString() + ")";
    }
}

public class Test {
    public static void main(String[] args) {
        Context ctx = new Context();
        Variable x = new Variable("x");
        Variable y = new Variable("y");
        Constant c = new Constant(true);
        ctx.assign(x, false);
        ctx.assign(y, true);    
        Expression exp = new Or(new And(c, x), new And(y, new Not(x)));
        System.out.println("x=" + x.interpret(ctx));
        System.out.println("y=" + y.interpret(ctx));
        System.out.println(exp.toString() + "=" + exp.interpret(ctx));
    }
}


附件列表

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

  1. Interpreter Expression 解释器模式 MD

    解释器模式 简介 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. linux下搭建svn服务器

    安装步骤如下: 1.yum install subversion   2.输入rpm -ql subversion查看安装位置,如下图:   我们知道svn在bin目录下生成了几个二进制文件. 输入 ...

  2. jQuery运维开发之第十七天

    JQuery 学习参考网址http://jquery.cuishifeng.cn/ python中叫模块,在DOM/BOM/Javascript中叫类库 现在的JQ版本有:1.x 2.x 3.x 建议 ...

  3. App适配iPhone 6/ Plus和iOS 8:10条小秘诀

    App适配iPhone 6/ Plus和iOS 8:10条小秘诀   iPhone 6iOS 8适配   (原文:raywenderlich 作者:Jack Wu 译者:@TurtleFromMars ...

  4. mysql的SQL_CALC_FOUND_ROWS 使用

    mysql的SQL_CALC_FOUND_ROWS 使用 标签: sqlmysqltable 2007-02-27 11:40 5073人阅读 评论(0) 收藏 举报  分类: Mysql数据库技术( ...

  5. C# 日期格式精确到毫秒 【转】

    有时候我们要对时间进行转换,达到不同的显示效果 默认格式为:2009-6-24 14:33:34 如果要换成成200906,06-2009,2009-6-24或更多的该怎么办呢 我们要用到:DateT ...

  6. 用STRACE解决公司真实故障一例

    这是相关分析文档.为了职业操守,已修改相关公司敏感信息~~~ ~~~~~~~~~~~~~~~~~~~~~~~~ 关于论坛每五分钟左右,会有warning.html跳转出现的原因调查 (warning. ...

  7. UpdateLayeredWindow, Layered Windows, codeproject

    http://www.codeproject.com/Articles/16362/Bring-your-frame-window-a-shadow http://www.codeproject.co ...

  8. 使用 Spring Data JPA 简化 JPA 开发

    从一个简单的 JPA 示例开始 本文主要讲述 Spring Data JPA,但是为了不至于给 JPA 和 Spring 的初学者造成较大的学习曲线,我们首先从 JPA 开始,简单介绍一个 JPA 示 ...

  9. Android 中使用MediaRecorder进行录像详解(视频录制)

    在这里给出自己的一个测试DEMO,里面注释很详细.简单的视频录制功能. package com.video; import java.io.IOException; import android.ap ...

  10. Git skills in reseting files

    How to uncommit files that were committed long time a ago?Note: Since all changes in the current wor ...