解析器模式

解释器模式介绍
解释器模式是一种用得比较少的行为模式,其提供了一种解释语言的语法或表达式,该模式定义了一个表达式接口,通过该接口解释一个特定的上下文。
解释器模式的定义
给定一个语言,定义它的文法的,并定义它的解释器,该解释器用来解释该文法的一个表示语言中的句子。这就是解释器模式,定义比较抽象,如四则运算,表达式a+b+c-d,通过解释器模式,解释表达式实现加减运算。这个表达式可以为任何遵循相同文法的表达式,如a+b,a-c,d-w等等。
解释器模式的使用场景
解释器模式的使用场景相当广泛,如四则运算,文字转换等,
加减法运算解释器模式UML类图
这里写图片描述

抽象表示类

public abstract class Expression {
    //key是参数,value是具体的数值
    public abstract int interpreter(HashMap<String, Integer> var);

}

变量解析器

public class VarExpression extends Expression{

    private String key;
    public VarExpression(String _key) {
        this.key = _key;
    }
    //从map中取值
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return var.get(this.key);//得到参数的值
    }
}

这个类解析很有意思,
抽象运算符号解析器

public abstract class SymbolExpression extends Expression{

    protected Expression left;
    protected Expression right;

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

}

每个运算符号都只和自己左右两个数字有关系,左右两个数字有可能也是一个解析结果,无论何种,结果都是Expression的实现类,于是在对运算符解析的子类中增加一个构造函数,传递左右两个表达式。具体的加,减法解析器如下所示:

加法解析器

public class AddExpression extends SymbolExpression {

    public AddExpression(Expression _left, Expression _right) {
        super(_left, _right);
    }

    //加法运算
    @Override
    public int interpreter(HashMap<String, Integer> var) {
        return left.interpreter(var) + right.interpreter(var);
    }

}

减法解析器

public class SubExpression extends SymbolExpression {

    public SubExpression(Expression _left, Expression _right) {
        super(_left, _right);
    }

    //减法运算
    @Override
    public int interpreter(HashMap<String, Integer> var) {
    return super.left.interpreter(var)-super.right.interpreter(var);
    }
}

加,减法类解析,里面的interpreter方法,最后是通过VarExpression的interpreter方法获取map集合里面参数的数值做加减法运算,返回运算结果。上面解析器的开发已经完成了,但需求还没有实现,需要对解析器封装,封装的类Calculator如下:

public class Calculator {

    private Expression expression;
    //构造方法并解析
    public Calculator(String expStr){

        Stack<Expression> stack = new Stack<>();

        char[] charArray = expStr.toCharArray();

        Expression left = null;
        Expression right = null;

        for(int i = 0 ; i < charArray.length; i++){
            switch (charArray[i]) {
                case '+':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new AddExpression(left, right));//运算的结果入栈
                    break;
                case '-':
                    left = stack.pop();
                    right = new VarExpression(String.valueOf(charArray[++i]));
                    stack.push(new SubExpression(left, right));
                    break;
                default:
                    stack.push(new VarExpression(String.valueOf(charArray[i])));//公式中的变量
                    break;
            }
        }
        this.expression = stack.pop();
    }

    public int run(HashMap<String, Integer> var){
        return this.expression.interpreter(var);
    }

}

Calculator构造函数接收一个表达式,然后把表达式转化为char数组,并判断运算符‘+’,‘-’。逐个循环字符数组,把参数压入栈,如果是运算符就出栈和下一个字符进行运算,再压入栈,后面都是同理。压如栈里面的都是VarExpression对象。这个对象实现的interpreter方法是返回map集合里面参数的数值,最后在AddExpression和SubExpression类的interpreter方法里面实现加发计算返回结果。
最后是客户端实现根据需求是客户能够修改表达式,所以通过客户端输入实现计算,代码如下:

public static void main(String[] args) {

        String expStr = null;
        HashMap<String, Integer> var = null;
        try {
            expStr = getExpStr();
            var = getValue(expStr);
        } catch (IOException e) {
            e.printStackTrace();
        }

        Calculator cal = new Calculator(expStr);
        System.out.println("运算结果为:" + expStr + "=" + cal.run(var));

    }

    public static String getExpStr() throws IOException{
        System.out.print("请输入表达式:");
        return (new BufferedReader(new InputStreamReader(System.in))).readLine();
    }

    public static HashMap<String, Integer> getValue(String expStr) throws IOException{
        HashMap<String, Integer> map = new HashMap<String,Integer>();
        for(char ch:expStr.toCharArray()){
            if (ch != '+' && ch != '-') {
            //重复的参数判断
                if (!map.containsKey(String.valueOf(ch))) {
                    System.out.println("请输入" + ch + "的值:");
                    String in = (new BufferedReader(new InputStreamReader(System.in))).readLine();
                    map.put(String.valueOf(ch), Integer.valueOf(in));
                }
            }
        }
        return map;
    }

执行结果

请输入表达式:a+b-s
请输入a的值:
10
请输入b的值:
20
请输入s的值:
15
运算结果为:a+b-s=15

这样就实现了加,减法运算,如果需要扩展添加乘除法运算,只要添加继承SymbolExpression类的乘除法类,再在Calculator类里面实现‘*’‘/’运算符号,并且要考虑表达式运算符的优先级。

最后来说一下解释器模式的优缺点:
优点:解释器是一个简单语法分析工具,它最显著的优点就是扩展性,修改语法规则只有修改相应的非终结符表达式就可以了,若扩展语法,则只要增加非终结符类就可以了。
缺点:每个语法都要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来了非常多的麻烦。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值