设计模式(十六)———解释器模式(Interprete Pattren):语法规则也是类

设计模式(十六)———解释器模式(Interprete Pattren):语法规则也是类

Scroll Down

Intent

给定一个语言,定义它的文法的一种表示,并定义个解释器,这个解释器使用该表示来解释语言中的句子。

应用实例

  • 编译器、运算表达式计算。

使用场景

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

优点

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

缺点

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

Class Diagram

image.png

AbstractExpression(抽象表达式)

AbstractExpression角色定义了语法树节点的共同接口(API)

TerminalExpression(终结符表达式)

TerminalExpression角色对应BNF中的终结符表达式。

NonTerminalExpression(非终结符表达式)

NonTerminalExpression角色对应BNF中的非终结符表达式。

Context(文脉,上下文)

Context角色为解释器进行语法解析提供了必要的信息。

Client(请求者)

为了推到语法书,Client角色调用TerminalExpression角色和NonTerminalExpression角色

Implementation

以下是一个规则检验器实现,具有 and 和 or 规则,通过规则可以构建一颗解析树,用来检验一个文本是否满足解析树定义的规则。

例如一颗解析树为 D And (A Or (B C)),文本 "D A" 满足该解析树定义的规则。

这里的 Context 指的是 String。

public abstract class Expression {
    public abstract boolean interpret(String str);
}
public class TerminalExpression extends Expression {

    private String literal = null;

    public TerminalExpression(String str) {
        literal = str;
    }

    public boolean interpret(String str) {
        StringTokenizer st = new StringTokenizer(str);
        while (st.hasMoreTokens()) {
            String test = st.nextToken();
            if (test.equals(literal)) {
                return true;
            }
        }
        return false;
    }
}
public class AndExpression extends Expression {

    private Expression expression1 = null;
    private Expression expression2 = null;

    public AndExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    public boolean interpret(String str) {
        return expression1.interpret(str) && expression2.interpret(str);
    }
}
public class OrExpression extends Expression {
    private Expression expression1 = null;
    private Expression expression2 = null;

    public OrExpression(Expression expression1, Expression expression2) {
        this.expression1 = expression1;
        this.expression2 = expression2;
    }

    public boolean interpret(String str) {
        return expression1.interpret(str) || expression2.interpret(str);
    }
}
public class Client {

    /**
     * 构建解析树
     */
    public static Expression buildInterpreterTree() {
        // Literal
        Expression terminal1 = new TerminalExpression("A");
        Expression terminal2 = new TerminalExpression("B");
        Expression terminal3 = new TerminalExpression("C");
        Expression terminal4 = new TerminalExpression("D");
        // B C
        Expression alternation1 = new OrExpression(terminal2, terminal3);
        // A Or (B C)
        Expression alternation2 = new OrExpression(terminal1, alternation1);
        // D And (A Or (B C))
        return new AndExpression(terminal4, alternation2);
    }

    public static void main(String[] args) {
        Expression define = buildInterpreterTree();
        String context1 = "D A";
        String context2 = "A B";
        System.out.println(define.interpret(context1));
        System.out.println(define.interpret(context2));
    }
}

输出结果

true
false