一、定义
给定一种语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解析语言中的句子。
简单理解:为了解释一种语言,而为语言创建的解释器。
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); } }
结果如下图