设计模式二十四章经之解释器模式

2018-06-22 17:39:25 浏览数 (1)

概述

解释器模式一般来说,我们用的比较少,它提供了一种解释语言的语法或者表达式的方式,比如说1 2,我们可以通过解释器模式告诉你这是一个加法。

使用场景

  • 如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
  • 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树。
  • 一些重复出现的问题可以用一种简单的语言来进行表达。
  • 一个简单语法需要解释的场景。

具体实现

我们现在通过一个简单的例子,比如向你解释这个文本是否包含某个内容。

我们先写个一个接口。这个接口的意图就是文本是否包含某个内容,返回一个boolean值。

代码语言:javascript复制
public interface IExpression {
    public boolean interpret(String context);
}

现在我们写一个类是实现这个接口,实现我们刚才所说的点:

代码语言:javascript复制
public class TerminalExpression implements IExpression {

   private String data;

   public TerminalExpression(String data){
      this.data = data; 
   }

   @Override
   public boolean interpret(String context) {
      if(context.contains(data)){
         return true;
      }
      return false;
   }
}

现在我们写2个类去实现我们刚才说的内容:

代码语言:javascript复制
public class OrExpression implements IExpression {

   private IExpression expr1 = null;
   private IExpression expr2 = null;

   public OrExpression(IExpression expr1, IExpression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {        
      return expr1.interpret(context) || expr2.interpret(context);
   }
}
代码语言:javascript复制
public class AndExpression implements IExpression {

   private IExpression expr1 = null;
   private IExpression expr2 = null;

   public AndExpression(IExpression expr1, IExpression expr2) { 
      this.expr1 = expr1;
      this.expr2 = expr2;
   }

   @Override
   public boolean interpret(String context) {        
      return expr1.interpret(context) && expr2.interpret(context);
   }
}

通过代码我们可以发现,一个是只要包含其一,另一个必须是都要包含,现在我们写一个Demo看看效果:

代码语言:javascript复制
public class Expression {
    public static IExpression getMaleExpression() {
        IExpression robert = new TerminalExpression("Robert");
        IExpression john = new TerminalExpression("John");
        return new OrExpression(robert, john);
    }

    public static IExpression getMarriedWomanExpression() {
        IExpression julie = new TerminalExpression("Julie");
        IExpression married = new TerminalExpression("Married");
        return new AndExpression(julie, married);
    }

    public static void main(String[] args) {
        IExpression isMale = getMaleExpression();
        IExpression isMarriedWoman = getMarriedWomanExpression();

        System.out.println("John is male? "   isMale.interpret("John"));
        System.out.println("Julie is a married women? "   isMarriedWoman.interpret("Married Julie"));
    }
}

运行得出:

代码语言:javascript复制
John is male? true
Julie is a married women? true

如果我们将代码改成:System.out.println("Julie is a married women? " isMarriedWoman.interpret("Married "));

那么运行结果则是:

代码语言:javascript复制
John is male? true
Julie is a married women? false

总结

优点:

  • 可扩展性比较好,灵活。
  • 增加了新的解释表达式的方式。
  • 易于实现简单文法。

缺点:

  • 可利用场景比较少。
  • 对于复杂的文法比较难维护。
  • 解释器模式会引起类膨胀。
  • 解释器模式采用递归调用方法。

0 人点赞