设计模式--解释器模式

Java工程源码

类图

这里写图片描述


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


优点
- 扩展性好,修改语法规则只要修改相应的非终结符表达式就可以了

缺点
- 容易引起类膨胀。每个语法都要产生一个非终结符表达式
- 采用递归方法,不易调试
- 效率问题。大量使用了循环和递归


注意事项
解释器模式一般用来解析比较标准的字符集,如SQL语法分析等


抽象表达式

public abstract class AbstractExpression {
    public abstract Object interpret(Context ctx);

    /**
     * 检验两个表达式在结构上是否相同
     *
     * @param exp 表达式
     * @return 是否相同
     */
    public abstract boolean equals(AbstractExpression exp);
}

终结符表达式

public abstract class TerminalExpression extends AbstractExpression {
}

非终结符表达式

public abstract class NonterminalExpression extends AbstractExpression {
    /**
     * 校验表达式结果是否是Boolean类型
     *
     * @param result 表达式结果
     * @param expStr 表达式
     * @throws IllegalArgumentException
     */
    public void checkBoolean(Object result, String expStr) throws IllegalArgumentException {
        if (!(result instanceof Boolean)) {
            throw new IllegalArgumentException("表达式" + expStr + "参数类型错误,参数类型应为:Boolean");
        }
    }
    /**
     * 校验表达式结果是否是Integer类型
     *
     * @param result 表达式结果
     * @param expStr 表达式
     * @throws IllegalArgumentException
     */
    public void checkInteger(Object result, String expStr) throws IllegalArgumentException {
        if (!(result instanceof Integer)) {
            throw new IllegalArgumentException("表达式" + expStr + "参数类型错误,参数类型应为:Integer");
        }
    }
}

变量终结符

public class Variable extends TerminalExpression {
    private String name;

    /**
     * 变量
     *
     * @param name 变量名
     */
    public Variable(String name) {
        this.name = name;
    }

    @Override
    public Object interpret(Context ctx) {
        return ctx.lookup(this);
    }

    @Override
    public boolean equals(AbstractExpression obj) {
        if (obj != null && obj instanceof Variable) {
            return this.name.equals(((Variable) obj).name);
        }
        return false;
    }


    @Override
    public String toString() {
        return name;
    }
}

整型终结符

public class MyInt extends TerminalExpression {
    private final int value;

    public MyInt(int value) {
        this.value = value;
    }

    @Override
    public Object interpret(Context ctx) {
        return value;
    }

    @Override
    public boolean equals(AbstractExpression exp) {
        if (exp != null && exp instanceof MyInt) {
            return this.value == ((MyInt) exp).value;
        }
        return false;
    }

    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

布尔型终结符

public class MyBoolean extends TerminalExpression {
    public static final MyBoolean TRUE = new MyBoolean(true);
    public static final MyBoolean FALSE = new MyBoolean(false);
    private final boolean value;

    public MyBoolean(boolean value) {
        this.value = value;
    }

    @Override
    public Object interpret(Context ctx) {
        return value;
    }

    @Override
    public boolean equals(AbstractExpression obj) {
        if (obj != null && obj instanceof MyBoolean) {
            return this.value == ((MyBoolean) obj).value;
        }
        return false;
    }


    @Override
    public String toString() {
        return String.valueOf(value);
    }
}

上下文

public class Context {
    /**
     * 变量存储区
     */
    private Map<Variable, TerminalExpression> map = new HashMap<>();

    /**
     * 变量赋值
     *
     * @param var   变量
     * @param value 值
     */
    public void assign(Variable var, TerminalExpression value) {
        map.put(var, value);
    }

    /**
     * 查看变量内容
     *
     * @param var 变量
     * @return 变量值
     * @throws IllegalArgumentException
     */
    public Object lookup(Variable var) throws IllegalArgumentException {
        TerminalExpression value = map.get(var);
        if (value == null) {
            throw new IllegalArgumentException();
        }
        return value.interpret(this);
    }
}

加运算表达式

public class Add extends NonterminalExpression {
    private final AbstractExpression left, right;

    public Add(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public Object interpret(Context ctx) {
        Object leftObj = left.interpret(ctx);
        Object rightObj = right.interpret(ctx);
        //参数检查
        checkInteger(leftObj, left.toString());
        checkInteger(rightObj, right.toString());
        return (Integer) leftObj + (Integer) rightObj;
    }

    @Override
    public boolean equals(AbstractExpression exp) {
        if (exp != null && exp instanceof Add) {
            return left.equals(((Add) exp).left) &&
                    right.equals(((Add) exp).right);
        }
        return false;
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " + " + right.toString() + ")";
    }
}

乘运算表达式

public class Multiply extends NonterminalExpression {
    private final AbstractExpression left, right;

    public Multiply(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public Object interpret(Context ctx) {
        Object leftObj = left.interpret(ctx);
        Object rightObj = right.interpret(ctx);
        //参数检查
        checkInteger(leftObj,left.toString());
        checkInteger(rightObj,right.toString());
        return (Integer) leftObj * (Integer) rightObj;
    }

    @Override
    public boolean equals(AbstractExpression exp) {
        if (exp != null && exp instanceof Multiply) {
            return left.equals(((Multiply) exp).left) &&
                    right.equals(((Multiply) exp).right);
        }
        return false;
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " * " + right.toString() + ")";
    }
}

与运算表达式

public class And extends NonterminalExpression {
    private final AbstractExpression left, right;

    public And(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public Object interpret(Context ctx) {
        Object leftObj = left.interpret(ctx);
        Object rightObj = right.interpret(ctx);
        //参数检查
        checkBoolean(leftObj, left.toString());
        checkBoolean(rightObj, right.toString());
        return (Boolean) leftObj && (Boolean) rightObj;
    }

    @Override
    public boolean equals(AbstractExpression obj) {
        if (obj != null && obj instanceof And) {
            return left.equals(((And) obj).left) &&
                    right.equals(((And) obj).right);
        }
        return false;
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " AND " + right.toString() + ")";
    }
}

或运算表达式

public class Or extends NonterminalExpression {
    private AbstractExpression left, right;

    public Or(AbstractExpression left, AbstractExpression right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public Object interpret(Context ctx) {
        Object leftObj = left.interpret(ctx);
        Object rightObj = right.interpret(ctx);
        //参数检查
        checkBoolean(leftObj, left.toString());
        checkBoolean(rightObj, right.toString());
        return (Boolean) leftObj || (Boolean) rightObj;
    }

    @Override
    public boolean equals(AbstractExpression obj) {
        if (obj != null && obj instanceof Or) {
            return left.equals(((Or) obj).left) &&
                    right.equals(((Or) obj).right);
        }
        return false;
    }

    @Override
    public String toString() {
        return "(" + left.toString() + " OR " + right.toString() + ")";
    }
}

非运算表达式

public class Not extends NonterminalExpression {
    private AbstractExpression exp;

    public Not(AbstractExpression exp) {
        this.exp = exp;
    }

    @Override
    public Object interpret(Context ctx) {
        Object expObj = exp.interpret(ctx);
        //参数检查
        checkBoolean(expObj, exp.toString());
        return !(Boolean) exp.interpret(ctx);
    }

    @Override
    public boolean equals(AbstractExpression obj) {
        if (obj != null && obj instanceof Not) {
            return exp.equals(((Not) obj).exp);
        }
        return false;
    }

    @Override
    public String toString() {
        return "(NOT " + exp.toString() + ")";
    }
}

场景类

public class Client {
    public static void main(String[] args) {
        Context ctx = new Context();
        // 变量x
        Variable x = new Variable("x");
        // 变量y
        Variable y = new Variable("y");
        // 变量z
        Variable z = new Variable("z");
        // 变量赋值
        ctx.assign(x, MyBoolean.FALSE);
        ctx.assign(y, MyBoolean.TRUE);
        ctx.assign(z, new MyInt(5));
        System.out.println("x=" + x.interpret(ctx));
        System.out.println("y=" + y.interpret(ctx));
        System.out.println("z=" + z.interpret(ctx));
        // 表达式(true AND x)
        AbstractExpression exp1 = new And(MyBoolean.TRUE, x);
        System.out.println(exp1.toString() + "=" + exp1.interpret(ctx));
        // 表达式((true AND x) OR (y AND (NOT x)))
        AbstractExpression exp2 = new Or(new And(MyBoolean.TRUE, x), new And(y, new Not(x)));
        System.out.println(exp2.toString() + "=" + exp2.interpret(ctx));
        // 表达式((z + 3) + 2)
        AbstractExpression exp3 = new Add(new Add(z, new MyInt(3)), new MyInt(2));
        System.out.println(exp3.toString() + "=" + exp3.interpret(ctx));
        // 表达式(2 + (z * 3))
        AbstractExpression exp4 = new Add(new MyInt(2), new Multiply(z, new MyInt(3)));
        System.out.println(exp4.toString() + "=" + exp4.interpret(ctx));

        System.out.println("表达式1,2是否是同一个表达式:" + exp1.equals(exp2));
    }
}

运行结果

x=false
y=true
z=5
(true AND x)=false
((true AND x) OR (y AND (NOT x)))=true
((z + 3) + 2)=10
(2 + (z * 3))=17
表达式1,2是否是同一个表达式:false
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章