行为型模式——解释器模式(四)

该项目源码地址:https://github.com/ggb2312/Code/tree/master/java-basic/design-pattern
(设计模式相关代码与笔记)

1. 定义

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

2. 适用场景

某个特定类型问题发生频率足够高

3. 类图与角色

解释器模式类图

AbstractExpression: 抽象表达式。声明一个抽象的解释操作,该接口为抽象语法树中所有的节点共享。
TerminalExpression: 终结符表达式。实现与文法中的终结符相关的解释操作。实现抽象表达式中所要求的方法。文法中每一个终结符都有一个具体的终结表达式与之相对应。
NonterminalExpression: 非终结符表达式。为文法中的非终结符相关的解释操作。
Context: 环境类。包含解释器之外的一些全局信息。
Client: 客户类。
抽象语法树描述了如何构成一个复杂的句子,通过对抽象语法树的分析,可以识别出语言中的终结符和非终结符类。 在解释器模式中由于每一种终结符表达式、非终结符表达式都会有一个具体的实例与之相对应,所以系统的扩展性比较好。

4. 相关设计模式

解释器模式与适配器模式
适配器模式是不知道预先要适配的规则,解释器模式要先把规则写好,根据规则解释。

5. 模式实例

背景:现在我们用解释器模式来实现一个基本的加、减、乘、除和求模运算。例如用户输入表达式“3 * 4 / 2 % 4”,输出结果为2。下图为该实例的UML结构图:

模式实例类图

抽象语法树

抽象语法树

抽象表达式:Node

public interface Node {
    public int interpret();
}

非终结表达式:ValueNode 主要用解释该表达式的值。

public class ValueNode implements Node
{
    private int value;
    
    public ValueNode(int value)
    {
        this.value=value;
    }
        
    @Override
    public int interpret()
    {
        return this.value;
    }
}

终结表达式抽象类,由于该终结表达式需要解释多个运算符号,同时用来构建抽象语法树:

public abstract class SymbolNode implements Node {
    protected Node left;
    protected Node right;

    public SymbolNode(Node left, Node right) {
        this.left = left;
        this.right = right;
    }
}

MulNode

public class MulNode extends SymbolNode {
    public MulNode(Node left, Node right) {
        super(left, right);
    }

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

ModNode

package com.desgin.pattern.behavioral.interpreter;

public class ModNode extends SymbolNode {
    public ModNode(Node left, Node right) {
        super(left, right);
    }

    @Override
    public int interpret() {
        return super.left.interpret() % super.right.interpret();
    }
}

DivNode

public class DivNode extends SymbolNode {
    public DivNode(Node left, Node right) {
        super(left, right);
    }

    @Override
    public int interpret() {
        return super.left.interpret() / super.right.interpret();
    }
}

Calculator

import java.util.Stack;

public class Calculator {
    private String statement;
    private Node node;

    public void build(String statement) {
        Node left = null, right = null;
        Stack stack = new Stack();

        String[] statementArr = statement.split(" ");

        for (int i = 0; i < statementArr.length; i++) {
            if (statementArr[i].equalsIgnoreCase("*")) {
                left = (Node) stack.pop();
                int val = Integer.parseInt(statementArr[++i]);
                right = new ValueNode(val);
                stack.push(new MulNode(left, right));
            } else if (statementArr[i].equalsIgnoreCase("/")) {
                left = (Node) stack.pop();
                int val = Integer.parseInt(statementArr[++i]);
                right = new ValueNode(val);
                stack.push(new DivNode(left, right));
            } else if (statementArr[i].equalsIgnoreCase("%")) {
                left = (Node) stack.pop();
                int val = Integer.parseInt(statementArr[++i]);
                right = new ValueNode(val);
                stack.push(new ModNode(left, right));
            } else {
                stack.push(new ValueNode(Integer.parseInt(statementArr[i])));
            }
        }
        this.node = (Node) stack.pop();
    }

    public int compute() {
        return node.interpret();
    }
}

客户端:Client

public class Client {
    public static void main(String args[]) {
        String statement = "3 * 2 * 4 / 6 % 5";
        Calculator calculator = new Calculator();
        calculator.build(statement);
        int result = calculator.compute();
        System.out.println(statement + " = " + result);
    }
}

测试结果:

测试结果

6. 优缺点

优点:

  • 语法由很多类表示,容易改变及扩展此”语言”

缺点:

  • 当语法规则数目太多时,增加了系统复杂度
    执行效率比较低,可利用场景比较少。

7. 扩展-JDK1.7源码以及框架中的解释器模式

java.util.regex.Pattern正则解释器,相当于是一个语法。

java.util.regex.Pattern正则解释器

Spring中的解释器

package com.desgin.pattern.behavioral.interpreter.springel;

import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * Create by lastwhisper on 2019/2/10
 */
public class SpringTest {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("100 * 2 + 400 * 1 + 66");
        int value = (int) expression.getValue();
        System.out.println(value);
    }
}

参考

https://www.cnblogs.com/chenssy/p/3346427.html

你可能感兴趣的:(行为型模式——解释器模式(四))