Java设计模式之解释器模式

概述

解释器模式是一种用得比较少的行为型模式.提供了一种解释语言的语法或表达式的方式.
通过定义一个表达式接口,解释一个特定的上下文.

定义

给定一个语言,解释器模式可以定义出其文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.

解释器中涉及到的文法,就是符合一定规则的语句结构.
如 abcd…….cdef(ab开头,ef结尾,中间N个cd)中,根据N值的不同,可以得到不同的字符串如,abef,abcdef,abcdcdef….
假设我们有如下推导式
S ::= abA*ef
A ::= cd
其中 ::=表示推导,*表示闭包,意思是A可以有0~N个重复,S是初始符号,abef和cd是终结符号.
像这样的从一个具体的符号出发,通过不断地应用一些产生式规则 从而生成一个字符串的集合,我们将描述这个集合的文法称为形式文法.

给定一个语言(如由abcdef六个字符组成的字符串集合),定义它的文法的一种表示(S::=abA*ef,A::=cd)并定义一个解释器,解释器使用该表示来解释语言中的句子.
其中的解释器类似一个翻译机

使用场景

  • 某个简单的语言需要解释执行并且可以将该语言中的语句表示为一个抽象语法树的时候.
  • 在某些特定的领域出现不断重复的问题时,可以将该领域的问题转化为一种语法规则下的语句,并构建解释器来解释该语句.

UML

Java设计模式之解释器模式_第1张图片

其中涉及到的角色有:

AbstractExpression: 抽象表达式,声明一个抽象的解释操作父类,定义一个抽象的解释方法,具体的实现由子类解释器完成/
TerminalExpression: 终结符表达式,实现文法中与终结符有关的解释操作,文法中每一个终结符都有一个具体的终结表达式与之对应
NonterminalExpression: 非终结符表达式,实现文法中与非终结符有关的解释操作
Context: 上下文环境类,包含解释器之外的全局信息
Client: 客户端,解析表达式,构建抽象语法树,执行具体的解释操作等.

实例

如下我们通过对算术表达式的解释来看一个解释器模式的实现,
如表达式m+n+p中,如果我们使用解释器模式对该表达式进行解释,那么m,n,p代表的三个字母可以看成是终结符号,而+代表的运算符则可以看成是非终结符号

  • 首先建立抽象解释器表示数学运算
public abstract class ArithmeticExpression {

  public abstract int interptet();
}

解释器中定义了interptet()方法,ArithmeticExpression有两个直接子类,NumExpression,和OperatorExpression

  • 建立NumExpression,对数字进行解释
public class NumExpression extends ArithmeticExpression {
  private int num;

  public NumExpression(int _num) {
    num = _num;
  }

  @Override public int interptet() {
    return num;
  }
}
  • 建立OperatorExpression,对运算符进行解释
public abstract class OperatorExpression extends ArithmeticExpression {
  protected ArithmeticExpression mArithmeticExpression1,mArithmeticExpression2;

  public OperatorExpression(ArithmeticExpression _arithmeticExpression1,
      ArithmeticExpression _arithmeticExpression2) {
    mArithmeticExpression1 = _arithmeticExpression1;
    mArithmeticExpression2 = _arithmeticExpression2;
  }
}
  • AdditionExpression,OperatorExpression的直接子类,加法运算解释器
public class AdditionExpression extends OperatorExpression {
  public AdditionExpression(ArithmeticExpression _arithmeticExpression1,
      ArithmeticExpression _arithmeticExpression2) {
    super(_arithmeticExpression1, _arithmeticExpression2);
  }

  @Override public int interptet() {
    return mArithmeticExpression1.interptet() + mArithmeticExpression2.interptet();
  }
}
  • 新增业务逻辑处理类
public class Calculator {

  protected Stack mArithmeticExpressionStack = new Stack<>();

  public Calculator(String expression) {
    ArithmeticExpression arithmeticExpression1, arithmeticExpression2;
    String[] elements = expression.split(" ");
    for (int i = 0; i < elements.length; ++i) {
      switch (elements[i].charAt(0)) {
        case '+':
          arithmeticExpression1 = mArithmeticExpressionStack.pop();
          arithmeticExpression2 = new NumExpression(Integer.valueOf(elements[++i]));
          mArithmeticExpressionStack.push(
              new AdditionExpression(arithmeticExpression1, arithmeticExpression2));
          break;
        default:
          mArithmeticExpressionStack.push(new NumExpression(Integer.valueOf(elements[i])));
          break;
      }
    }
  }

  public int calculate() {
    return mArithmeticExpressionStack.pop().interptet();
  }
}
  • 客户端调用
// 解释计算123+124+125+126的运算结果
Calculator calculator = new Calculator("123+124+125+126");
   Log.d(TAG, "setBtnClick: -->" + calculator.calculate());

优缺点

优点

  • 灵活性强,如上边的例子,当我们想对文法规则进行扩展延伸时,只需要增加相应的非终结符解释器,并在构建语法树的时候使用新增的解释器对象进行具体的解释即可.

缺点

  • 因为每一条文法都可以对应至少一个解释器,会生成大量的类,导致后期维护困难,而且对应复杂的文法,构建语法树会显得异常繁琐.

实例代码

DesignPatterns

你可能感兴趣的:(设计模式,Java基础,Java设计模式)