行为型模式——解释器模式

2020-08-23  本文已影响0人  Doooook

解释器模式(Interpreter Pattern):定义一个语言的文法,并且建立一个解释器来解释该语言中的句子,这里的 “语言” 是指使用规定格式和语法的代码。解释器模式是一种类行为型模式。

image.png
解释器模式由以下类组成:

这里我们选择一个简单的语法作为例子。我们将应用解释器模式来解析带有一个变量的简单函数f(x),实现简单的加、减、乘。
为了简单,我们选择逆波兰表示法,这是一种在运算符末尾添加操作数的表示法。1+2变为1 2 +,(1+2)*3变为1 2 + 3 *。优点是不再需要括号,因此它简化了任务。

Interpreter解释器接口

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:54
 * @description: 解释器
 * 使用逆波兰表示法(后缀表达式,优点是不再需要括号),如:
 * 1 2 +(等同于1+2);
 * 1 2 + 3 *(等同于(1+2)*3)
 */
public interface Interpreter {
    /**
     * 解释器
     * @return
     */
    float interpret();
}

非终结符表达式,对整数进行解释

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 21:07
 * @description: 非终结符表达式,对整数进行解释
 */
public class NumberInterpreter implements Interpreter {
    private float number;

    public NumberInterpreter(float number) {
        this.number = number;
    }

    @Override
    public float interpret() {
        return number;
    }
}

终结符表达式,对加法进行解释

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:55
 * @description: 终结符表达式,对加法进行解释
 */
public class PlusInterpreter implements Interpreter {

    /**
     * 表达式的左边
     */
    private Interpreter left;
    /**
     * 表达式的右边
     */
    private Interpreter right;

    public PlusInterpreter(Interpreter left, Interpreter right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret() {
        return left.interpret() + right.interpret();
    }
}

终结符表达式,对减法进行解释

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:55
 * @description: 终结符表达式,对减法进行解释
 */
public class MinusInterpreter implements Interpreter {

    /**
     * 表达式的左边
     */
    private Interpreter left;
    /**
     * 表达式的右边
     */
    private Interpreter right;

    public MinusInterpreter(Interpreter left, Interpreter right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret() {
        return right.interpret() - left.interpret();
    }
}

终结符表达式,对乘法进行解释

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 21:07
 * @description: 终结符表达式,对乘法进行解释
 */
public class MultiInterpreter implements Interpreter {

    /**
     * 表达式的左边
     */
    private Interpreter left;
    /**
     * 表达式的右边
     */
    private Interpreter right;

    public MultiInterpreter(Interpreter left, Interpreter right) {
        this.left = left;
        this.right = right;
    }

    @Override
    public float interpret() {
        return left.interpret() * right.interpret();
    }
}

操作解释器,操作语法树

/**
 * @author: Jay Mitter
 * @date: 2020-08-23 20:58
 * @description: 操作解释器,操作语法树
 */
public class Evaluator {

    public float evaluate(String expression) {
        Stack<Interpreter> stack = new Stack<>();
        float result = 0;
        for (String token : expression.split(" ")) {
            if (isOperator(token)) {
                Interpreter exp = null;
                if ("+".equals(token)) {
                    exp = stack.push(new PlusInterpreter(stack.pop(), stack.pop()));
                } else if ("-".equals(token)) {
                    exp = stack.push(new MinusInterpreter(stack.pop(), stack.pop()));
                } else if ("*".equals(token)) {
                    exp = stack.push(new MultiInterpreter(stack.pop(), stack.pop()));
                }
                if (null != exp) {
                    result = exp.interpret();
                    stack.push(new NumberInterpreter(result));
                }
            } else if (isNumber(token)) {
                stack.push(new NumberInterpreter(Float.parseFloat(token)));
            }
        }
        return result;
    }

    private boolean isOperator(String token) {
        return "+".equals(token) || "-".equals(token) || "*".equals(token);
    }

    private boolean isNumber(String token) {
        try {
            Float.parseFloat(token);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

测试:

/**
     * 行为型模式——解释器模式
     */
    @Test
    public void testBehaviorInterpreter() {
        Evaluator evaluator = new Evaluator();
        // 1+2=3
        float result = evaluator.evaluate("1 2 +");
        System.out.println(result);
        // 4+3-2=5
        result = evaluator.evaluate("4 3 + 2 -");
        System.out.println(result);
        // (4+3)*2
        result = evaluator.evaluate("4 3 + 2 *");
        System.out.println(result);
    }

测试结果:

3.0
5.0
14.0

解释器模式总结

解释器模式为自定义语言的设计和实现提供了一种解决方案,它用于定义一组文法规则并通过这组文法规则来解释语言中的句子。虽然解释器模式的使用频率不是特别高,但是它在正则表达式XML文档解释等领域还是得到了广泛使用。

主要优点

主要缺点

适用场景

解释器模式的典型应用

Spring EL表达式中的解释器模式

Spring EL表达式相关的类在org.springframework.expression包下,这里只是做简单的测试,需要进一步了解,请阅读源码。

/**
     * 行为型模式——Spring EL表达式
     */
    @Test
    public void testBehaviorInterpreter1() {
        // 1. 构建解析器
        ExpressionParser parser = new SpelExpressionParser();
        // 2. 解析表达式
        Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
        // 3. 获取结果
        int result = (Integer) expression.getValue();
        // 结果:666
        System.out.println(result);
    }

结果:

666

参考:https://blog.csdn.net/wwwdc1012/article/details/86444352

上一篇 下一篇

猜你喜欢

热点阅读