# 23种设计模式-解释器模式

# 1.解释器模式

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

# 优缺点

# 优点:

解释器是一个简单的语法分析工具,它最显著的优点就是扩展性,修改语法规则只需要修改相应的非终结符就可以了,若扩展语法,只需要增加非终结符类就可以了。 增加了新的解释表达式的方式。 易于实现文法。

# 缺点:

解释器模式会引起类的膨胀,每个语法都需要产生一个非终结符表达式,语法规则比较复杂时,就可能产生大量的类文件,为维护带来非常多的麻烦。 效率低下,采用递归调用方法,每个非终结符表达式只关心与自己相关的表达式,每个表达式需要知道最终的结果,必须通过递归方式,无论是面向对象的语言还是面向过程的语言,递归都是一个不推荐的方式。由于使用了大量的循环和递归,效率是一个不容忽视的问题。特别是用于解释一个解析复杂、冗长的语法时,效率是难以忍受的。

# 使用场景

1有一个简单的语法规则,比如一个sql语句,如果我们需要根据sql语句进行rm转换,就可以使用解释器模式来对语句进行解释。

2一些重复发生的问题,比如加减乘除四则运算,但是公式每次都不同,有时是a+b-cd,有时是ab+c-d,等等,公式千变万化,但是都是由加减乘除四个非终结符来连接的,这时我们就可以使用解释器模式。

# 实现方式

# 抽象表达式:Node.java。

public interface Node{
    public int interpret();
}

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

public class ValueNode implements Node{
    private int value;
    
    public ValueNode(int value){
        this.value=value;
    }
        
    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.java:

public class MulNode extends SymbolNode{
    public MulNode(Node left,Node right){
        super(left,right);
    }
    
    public int interpret(){
        return left.interpret() * right.interpret();
    }
}

# ModNode.java:

public class ModNode extends SymbolNode{
    public ModNode(Node left,Node right){
        super(left,right);
    }
    
    public int interpret(){
        return super.left.interpret() % super.right.interpret();
    }
}

# DivNode.java:

public class DivNode extends SymbolNode{
    public DivNode(Node left,Node right){
        super(left,right);
    }
    
    public int interpret(){
        return super.left.interpret() / super.right.interpret();
    }
}

# Calculator.java:

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();
    }
}

# 测试类

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);    
    }
}

参考博客:https://blog.csdn.net/a745233700/article/details/83750731