work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

解释器模式

Posted on 2019-02-28 20:45  work hard work smart  阅读(222)  评论(0编辑  收藏  举报

一、定义

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

简单理解:为了解释一种语言,而为语言创建的解释器。

C#代码,Java代码的编译器就相当于一个解释器。

类型: 行为型

 

二、适用场景

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

如程序中有很多日志,对日志进行解析就是解析器。日常使用比较少(低频)。

 

三、解释器-优点

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

 

四、解释器模式-缺点

1、当语法规则数目太多时,增加了系统的复杂度

规则太多,每个规则都要写一个类。

 

五、解释器模式-相关设计模式

1、解释器模式和适配器模式

适配器模式是不需要预先知道要适配的规则

解析器模式把规则写好,根据规则执行解释。

 

六、Coding

1、Interpreter 接口

public interface Interpreter {
    //解释
    int interpret();
}

  

2、 加法解释器 AddInterprete

/**
 * 加法解释器
 */
public class AddInterpreter  implements  Interpreter{

    private Interpreter firstExpression, secondExpression;

    public AddInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        //第一个表达式的解释+第二个表达式的解释
        return firstExpression.interpret() + secondExpression.interpret();
    }

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

  

3、 乘法解释器 MultiInterpreter

/**
 * 乘法解释器
 */
public class MultiInterpreter implements  Interpreter{

    private Interpreter firstExpression, secondExpression;

    public MultiInterpreter(Interpreter firstExpression, Interpreter secondExpression) {
        this.firstExpression = firstExpression;
        this.secondExpression = secondExpression;
    }

    @Override
    public int interpret() {
        //第一个表达式的解释*第二个表达式的解释
        return firstExpression.interpret() * secondExpression.interpret();
    }

    @Override
    public String toString() {
        return "*";
    }
}

  

4、数字解释器NumberInterprete

/**
 * 数字解释器
 */
public class NumberInterpreter implements  Interpreter{

    private int number;

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

    public NumberInterpreter(String number) {
        this.number = Integer.parseInt(number);
    }

    @Override
    public int interpret() {
        return this.number;
    }


}

  

5、工具类OperatorUtil 

public class OperatorUtil {

    /**
     * 是否是操作符
     * @param symbol
     * @return
     */
    public  static  boolean isOperator(String symbol){
        return  ( "+".equals(symbol) || "*".equals(symbol));
    }

    public static  Interpreter getExpressionObject(Interpreter firstExpression, Interpreter secondExpression, String symbol){
        if("+".equals(symbol)){
            return  new AddInterpreter(firstExpression, secondExpression);
        }else if("*".equals(symbol)){
            return  new MultiInterpreter(firstExpression, secondExpression);
        }
        return  null;
    }
}

  

6、LarryExpressionParser 类

public class LarryExpressionParser {
    private Stack<Interpreter> stack = new Stack<>();

    public  int parse(String str){
        String[] strInemArray = str.split(" ");
        for(String item : strInemArray){
            if(!OperatorUtil.isOperator(item)){
                Interpreter numberExpression = new NumberInterpreter(item);
                stack.push(numberExpression);
                System.out.println(String.format("入栈:%d", numberExpression.interpret()));
            }else {
                //是运算符号可以计算
                Interpreter firstExpression = stack.pop();
                Interpreter secondExpression = stack.pop();
                System.out.println(String.format("出栈: %d 和 %d", firstExpression.interpret(), secondExpression.interpret()));
                Interpreter operator = OperatorUtil.getExpressionObject(firstExpression, secondExpression, item);
                System.out.println(String.format("应用运算符: %s", operator));
                int result = operator.interpret();
                NumberInterpreter resultExpress = new NumberInterpreter(result);
                stack.push(resultExpress);
                System.out.println(String.format("阶段结果入栈: %d", resultExpress.interpret()));
            }

        }
        int result = stack.pop().interpret();
        return  result;

    }
}

  

7、测试类

public class Test {

    public static void main(String[] args) {
        String input = "6 100 11 + *"; //(100+11)*6=666
        LarryExpressionParser larryExpressionParser = new LarryExpressionParser();
        int result = larryExpressionParser.parse(input);
        System.out.println("解释器计算结果:" +  result);
    }
}

  

8、测试结果

 

 9、UML图

 

七、在源码中的应用

1、Pattern正则

 

2、Spring EL表达式

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


public class SpringTest {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression("100 * 3 + 500 * 2 + 6 * 5");
        int result = (Integer)expression.getValue();
        System.out.println(result);
    }
}

  结果如下图