设计模式:023_解释器模式

60 阅读3分钟

解释器模式

解释器模式(Interpreter Pattern),是指给定一个语言(表达式),定义它的文法的一种表示,并定义一个解释器,使用该解释器来解释语言中的句子(表达式)

作用

  • 易于实现语法,一条语法用一个解释器对象解释执行
  • 易于扩展新语法,只需创建对应解释器,抽象语法树时使用即可

缺点

  • 可使用场景少,复用性不高,除了发明新的编程语言或对某些新硬件进行解释外,很少用,特定数据结构,扩展性也低
  • 维护成本高,每种规则至少要定义一个解释类,语法规则越多,类越难管理和维护
  • 执行效率低,递归调用方法,解释句子语法复杂时,会执行大量循环语句

适用场景

  • 可以将一个需要解释执行的语言中的句子表示为一个抽象语法树
  • 一些重复出现的问题可以用一种简单的语言来表达
  • 一个简单语法需要解释的场景
  • 典型场景:编译器、规则引擎、正则表达式、运算表达式

类图

解释器模式类图.png

  • 抽象表达式(Abstract Expression):定义解释器的接口,约定解释器的解释操作,主要包含解释方法 interpret()。
  • 终结符表达式(Terminal Expression):是抽象表达式的子类,实现文法中元素相关联的解释操作,文法中的每一个元素都有一个具体终结表达式与之相对应。
  • 非终结符表达式(Nonterminal Expression):也是抽象表达式的子类,实现文法中规则关联的解释操作,文法中的每条规则对应于一个非终结符表达式,一般是文法中的运算符或其他关键字。
  • 上下文(Context):通常包含各个解释器需要的数据或是公共的功能,一般用来传递被所有解释器共享的数据,后面的解释器可以从这里获取这些值。

代码表达

// 抽象表达式(Abstract Expression)
public abstract class Expression {
    public abstract int interpreter(Context context);
}
// 终结符表达式(Terminal Expression)
public class VarExpression extends Expression {
    private String key;

    public VarExpression(String key) {
        this.key = key;
    }

    @Override
    public int interpreter(Context context) {
        return context.getValue(key);
    }
}
// 非终结符表达式(Nonterminal Expression)
public class SymbolExpression extends Expression {
    protected Expression left;
    protected Expression right;

    public SymbolExpression(Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    // SymbolExpression 的功能由具体子类实现,此处默认空实现
    @Override
    public int interpreter(Context context) {
        return 0;
    }
}

public class AddExpression extends SymbolExpression {
    public AddExpression(Expression left, Expression right) {
        super(left, right);
    }

    // 加法解释器
    @Override
    public int interpreter(Context context) {
        return super.left.interpreter(context) + super.right.interpreter(context);
    }
}

public class SubExpression extends SymbolExpression {
    public SubExpression(Expression left, Expression right) {
        super(left, right);
    }

    // 减法解释器
    @Override
    public int interpreter(Context context) {
        return super.left.interpreter(context) - super.right.interpreter(context);
    }
}
// 上下文(Context)
public class Context {
    // HashMap 中包含各个解释器需要的数据
    private HashMap<String, Integer> var;

    public Context() {
        this.var = new HashMap<>();
    }

    public void addEntry(String key, int value) {
        var.put(key, value);
    }

    public int getValue(String key) {
        return var.get(key);
    }
}
// 具体逻辑实现类,供客户端调用
public class Calculator {
    // 实现加减表达式具体逻辑
    public Calculator(String exp, Context context) {
        Stack<Expression> stack = new Stack<>();
        char[] charArray = exp.toCharArray();
        Expression left = null;
        Expression right = null;
        for (int i = 0; i < charArray.length; i++) {
            switch (charArray[i]) {
                case '+':
                    left = stack.pop();
                    i++;
                    right = new VarExpression(String.valueOf(charArray[i]));
                    stack.push(new AddExpression(left, right));
                    break;
                case '-':
                    left = stack.pop();
                    i++;
                    right = new VarExpression(String.valueOf(charArray[i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    stack.push(new VarExpression(String.valueOf(charArray[i])));
                    break;
            }
        }
        int result = stack.pop().interpreter(context);
        System.out.println(result);
    }
}

客户端调用

String exp = "a+b-c";
Context context = new Context();
context.addEntry("a", 30);
context.addEntry("b", 40);
context.addEntry("c", 50);
new Calculator(exp, context);