设计模式-解析器模式(二十一)

解析器模式
给定一个语言,定义它的文法表示,并定义一个解释器,这个解释器使用该标识来解释语言中的句子。
这种模式被用在 SQL 解析、符号处理引擎等。

Jsoup这个源码里面用到,代码简单,功能狠强大.

可利用场景比较少,JAVA 中如果碰到可以用 expression4J 代替。

  • 上类图:
设计模式-解析器模式(二十一)_第1张图片
解析器模式.png
  • 代码示例:
  1. 创建表达式接口
package com.byedbl.interpreter;

/**
 * The interface of our BooleanExp Interpreter
 * BooleanExp definition is:
 * BooleanExp ::= VariableExp | Constant | OrExp | AndExp
 * | NotExp | '(' BooleanExp ')'
 * AndExp ::= BooleanExp 'and' BooleanExp
 * OrExp ::= BooleanExp 'or' BooleanExp
 * NotExp ::= BooleanExp 'not' BooleanExp
 * Constant ::= 'true' | 'false'
 * VariableExp ::= 'A' | 'B' | ... | 'Z'
 */
public interface BooleanExp {
    boolean evaluate(Context c);

    BooleanExp replace(String var, BooleanExp exp);

    BooleanExp copy();
}
  1. 创建一个终结符表达式
package com.byedbl.interpreter;

/**
 * A variable expression implements BooleanExp
 * A terminal expression
 */
public class VariableExp implements BooleanExp {
    private String name;

    public VariableExp(String _name) {
        name = _name;
    }

    @Override
    public boolean evaluate(Context c) {
        return c.lookUp(name);
    }

    @Override
    public BooleanExp copy() {
        return new VariableExp(name);
    }

    @Override
    public BooleanExp replace(String var, BooleanExp exp) {
        if (var.equals(name)) {
            return exp.copy();
        } else {
            return new VariableExp(name);
        }
    }

}
  1. 创建非终结符表达式
package com.byedbl.interpreter;

/**
 * A NonterminalExpression
 */
public class AndExp implements BooleanExp {
    private BooleanExp operand1;
    private BooleanExp operand2;

    public AndExp(BooleanExp oper1, BooleanExp oper2) {
        operand1 = oper1;
        operand2 = oper2;
    }

    @Override
    public boolean evaluate(Context c) {
        return operand1.evaluate(c) &&
                operand2.evaluate(c);
    }

    @Override
    public BooleanExp copy() {
        return new AndExp(operand1.copy(), operand2.copy());
    }

    @Override
    public BooleanExp replace(String var, BooleanExp exp) {
        return new AndExp(
                operand1.replace(var, exp),
                operand2.replace(var, exp)
        );
    }
}
package com.byedbl.interpreter;

/**
 * A NonterminalExpression
 */
public class NotExp implements BooleanExp {
    private BooleanExp opernot1;

    public NotExp(BooleanExp oper1) {
        opernot1 = oper1;
    }

    @Override
    public boolean evaluate(Context c) {
        return !(opernot1.evaluate(c));
    }

    @Override
    public BooleanExp copy() {
        return new NotExp(opernot1.copy());
    }

    @Override
    public BooleanExp replace(String var, BooleanExp exp) {
        return new NotExp(opernot1.replace(var, exp));
    }
}
package com.byedbl.interpreter;

/**
 * A NonterminalExpression
 */
public class OrExp implements BooleanExp {
    private BooleanExp operor1;
    private BooleanExp operor2;

    public OrExp(BooleanExp oper1, BooleanExp oper2) {
        operor1 = oper1;
        operor2 = oper2;
    }

    @Override
    public boolean evaluate(Context c) {
        return operor1.evaluate(c) ||
                operor2.evaluate(c);
    }

    @Override
    public BooleanExp copy() {
        return new OrExp(operor1.copy(), operor2.copy());
    }

    @Override
    public BooleanExp replace(String var, BooleanExp exp) {
        return new OrExp(
                operor1.replace(var, exp),
                operor2.replace(var, exp)
        );
    }
}
  1. 环境角色
package com.byedbl.interpreter; /**
 * A Context to record variable value
 */

import java.util.Hashtable;

public class Context {
    private Hashtable context = new Hashtable<>();

    public void assign(String name, boolean val) {
        context.put(name, val);
    }

    public boolean lookUp(String name) {
        return context.get(name);
    }

    public Context() {
    }
}
  1. 客户端用法
package com.byedbl.interpreter; /**
 *
 */

public class Test  {
    public static void main(String[] args) {
        // Test :
        //         (true and x) and (y and (not x))
        Context context = new Context();
       
        VariableExp x = new VariableExp("X");
        VariableExp y = new VariableExp("Y");
        VariableExp bTure = new VariableExp("true");
        VariableExp bFalse = new VariableExp("false");

        context.assign("true", true);
        context.assign("false", false);
        context.assign("X", false);
        context.assign("Y", true);
        
        BooleanExp expression = new AndExp(
            new AndExp(bTure, x),
            new AndExp(y, new NotExp(x))
        );
        boolean result = expression.evaluate(context);
        System.out.println("The result is:" + result);
    }
}

你可能感兴趣的:(设计模式-解析器模式(二十一))