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

1、模式简介

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

  如果一种特定类型的问题发生频率足够高,那么可能就值得将该问题的各个实例表述为一种简单语言中的一个句子,这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。

解释器模式的优点:

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

解释器模式的缺点:

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

解释器模式的使用场景:

  • 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树;
  • 一些重复出现的问题可以用一种简单的语言来进行表达;
  • 一个简单语法需要解释的场景。

 

2、案例

  在本例中我们定义一个解释器来解决日常的算数问题,如:(a + b) / (a - b + 6) * a。具体代码如下:

  在解释器模式中,每个操作或参数都可以被抽象成一个表达式,因此我们首先定义一个表达式抽象类Expression,代码如下:

public abstract class Expression {
    protected String key;

    public String getKey() {
        return key;
    }

    public abstract Expression interpret(Context context);
}

  变量表达式VariableExpression中的代码:

public class VariableExpression extends Expression {
    private Integer value;

    public VariableExpression(String key, Integer value) {
        super.key = key;
        this.value = value;
    }

    public Integer getValue() {
        return value;
    }

    @Override
    public Expression interpret(Context context) {
        context.addVariable(super.key, value);
        return this;
    }
}

  加减乘除表达式的代码,这里以除法表达式DivideExpression中的代码为例:

public class DivideExpression extends Expression {
    private String resultExpressionKey;
    private Expression leftExpression;
    private Expression rightExpression;

    public DivideExpression(String resultExpressionKey, Expression leftExpression, Expression rightExpression) {
        this.resultExpressionKey = resultExpressionKey;
        this.leftExpression = leftExpression;
        this.rightExpression = rightExpression;
    }

    @Override
    public Expression interpret(Context context) {
        Integer rightVariableValue = ((VariableExpression) rightExpression).getValue();
        if (rightVariableValue != 0) {
            return new VariableExpression(resultExpressionKey,
                    ((VariableExpression) leftExpression).getValue() / rightVariableValue);
        }
        return null;
    }
}

  测试类Test中的代码如下:

/**
 * 计算:(a + b) / (a - b + 6) * a
 */
public class Test {
    public static void main(String[] args) {
        // 上下文对象
        Context context = new Context();
        // 向上下文对象中添加变量
        VariableExpression a = (VariableExpression) new VariableExpression("a", 11).interpret(context);
        VariableExpression b = (VariableExpression) new VariableExpression("b", 10).interpret(context);
        VariableExpression c = new VariableExpression("c", 6);

        // 开始计算
        Expression tmpResult1 = new AddExpression("tmp1", a, b).interpret(context);
        Expression tmpResult2 = new MinusExpression("tmp2", a, b).interpret(context);
        Expression tmpResult3 = new AddExpression("tmp3", tmpResult2, c).interpret(context);
        Expression tmpResult4 = new DivideExpression("tmp4", tmpResult1, tmpResult3).interpret(context);
        Expression tmpResult5 = new MultiplyExpression("tmp5", tmpResult4, a).interpret(context);

        // 打印结果
        System.out.println("结果是:" + ((VariableExpression) tmpResult5).getValue());
    }
}

  运行结果如下图所示:



  最后贴出解释器模式在GitHub中的代码地址:【GitHub - Interpreter】

posted on 2016-12-22 14:37  ITGungnir  阅读(240)  评论(0编辑  收藏  举报

导航