解释器模式

2367 查看

描述:对一个表达式进行解释时,将表达式分为终结符、非终结符、运算环境,这样区分可以把表达式的各个部分独立出来扩展。

名称解释:

  1. 表达式:一条运算语句,如c = a + b,它有一个解释方法,可以计算表达式结果
  2. 终结符:表达式中的变量,如a、b,终结符表达式负责解释终结符,即计算结果
  3. 非终结符:表达式中的运算符,如+,非终结符表达式负责计算非终结符的结果
  4. 运算环境:负责给终结符赋值,如a=1

场景:写个解释器,解释a+b=3,其中a=1,b=2,c=0,另外扩展一个相反数运算使-a=-1。

实现:

抽象一个表达式,负责解释终结符或者非终结符,其定义一个解释方法,计算表达式的值,同时覆盖equals和hashCode方法,方便判断两个表达式是否相同

abstract class Expression {
    String name;
    Expression(String name) {
        this.name = name;
    }
    abstract int interpret(Context ctx);
    @Override
    public boolean equals(Object obj) {
        if(null == obj) {
            return false;
        }
        if(obj instanceof String && name.equals(obj)) {
            return true;
        }
        return false;
    }
    @Override
    public int hashCode() {
        return name.hashCode();
    }
}

定义一个终结符表达式,也就是负责计算变量的值

class Variable extends Expression {
    Variable(String name) {
        super(name);
    }
    @Override
    int interpret(Context ctx) {
        return ctx.lookup(this);
    }
}

定一个非终结符表达式,其名为加法,负责计算两个终结符的值

class AddExpression extends Expression {
    Expression var1;
    Expression var2;
    AddExpression(Expression var1, String name, Expression var2) {
        super(name);
        this.var1 = var1;
        this.var2 = var2;
    }
    @Override
    int interpret(Context ctx) {
        return var1.interpret(ctx) + var2.interpret(ctx);
    }
}

如果想扩展一种运算,可以直接定义一个非终结符表达式,比如定义一个求相反数的运算

//一个数的相反数
class OppositeExpression extends Expression {
    Expression var;
    OppositeExpression(String name, Expression var) {
        super(name);
        this.var = var;
    }
    @Override
    int interpret(Context ctx) {
        return -var.interpret(ctx);
    }
}

定义一个运算环境,用于给变量赋值

class Context {
    Map<Expression, Integer> map = new HashMap<Expression, Integer>();
    void assign(Expression var, int value) {
        map.put(var, value);
    } 
    int lookup(Expression var) {
        Object obj = map.get(var);
        if(null == obj) {
            // 如果变量未初始化,默认是0
            return 0;
        }
        return (Integer) obj;
    }
}

客户端调用:

public static void main(String[] args) {
    Context ctx = new Context();
    Variable a = new Variable("a");
    Variable b = new Variable("b");
    Variable c = new Variable("c"); // 不初始化,默认为0
    ctx.assign(a, 1);
    ctx.assign(b, 2);
    System.out.println("a = " + a.interpret(ctx));
    System.out.println("b = " + b.interpret(ctx));
    System.out.println("c = " + c.interpret(ctx));
    // 相反数运算
    OppositeExpression opposite = new OppositeExpression("-", a);
    int rs = opposite.interpret(ctx);
    String exp = String.format("%s%s = %d", opposite.name, a.name, rs);
    System.out.println(exp);
    // 加运算
    AddExpression add = new AddExpression(a, "+", b);
    rs = add.interpret(ctx);
    exp = String.format("%s %s %s = %d", a.name, add.name, b.name, rs);
    System.out.println(exp);
}

结果:

a = 1
b = 2
c = 0
-a = -1
a + b = 3