书接上回,本篇讲一下行为型模式-解释器模式
定义:给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子。
大白话:设计一个程序,能解析拥有一定规则的表达式。比如正则表达式解析器。
UML图:

Expression:定义语法解析器的接口,约定解析器的解释操作
- /**
- * 语法表达式
- */
- public interface Expression {
- /**
- * 语法解析
- */
- void interpret();
- }
Interpret1Expression/Interpret2Expression:表达式解析器,解析表达式中特定语法,一个解析器对应一个语法规则。
- /**
- * 子表达式(解析1)
- * 负责完整表达式中一段解析
- */
- public class Interpret1Expression implements Expression{
- @Override
- public void interpret() {
- System.out.println("解析表达式中一段:子表达式1");
- }
- }
- /**
- * 子表达式(解析2)
- * 负责完整表达式中一段解析
- */
- public class Interpret2Expression implements Expression{
- @Override
- public void interpret() {
- System.out.println("解析表达式中一段:子表达式2");
- }
- }
TerminalExpression:也是一个表达式解析器,一般表示终结,得出结果的语法,比如四则运算中,最后等于操作。
- /**
- * 子表达式(解析3)
- * 负责完整表达式中一段解析--表示解析终止
- */
- public class TerminalExpression implements Expression{
- @Override
- public void interpret() {
- System.out.println("解析表达式中一段:终止表达式");
- }
- }
ExpressionInterpretParser:语法表达式解析器,这这个类中调用其他子解析器完整解析整个语法表达式式。担当总控的角色。
- /**
- * 表达式解析器
- */
- public class ExpressionInterpretParser {
- /**
- * 指定表达式解析
- * @param express
- */
- public void parse(String express){
- System.out.println("表达式:" + express);
-
- System.out.println("调用解析器:" );
- new Interpret1Expression().interpret();
- new Interpret2Expression().interpret();
- new TerminalExpression().interpret();
- }
- }
App:客户端,上面逻辑调用者。
- public class App {
-
- public static void main(String[] args) {
- ExpressionInterpretParser interpret = new ExpressionInterpretParser();
- interpret.parse("这是一个表达式");
- }
- }
结果:
- 表达式:这是一个表达式
- 调用解析器:
- 解析表达式中一段:子表达式1
- 解析表达式中一段:子表达式2
- 解析表达式中一段:终止表达式
需求:设计一个解析器,能解析加减乘除运算
最终表达式:1 2 3 4 5 + - * /
预想结果: (((1+2)-3) *4) / 5 = 0

Expression:定义解析解析语法规则
SubExpression / MulExpression / DivExpression / AddExpression:分别是加减乘除语法解析规则实现
NumExpression:数字语法解析规则实现
ExpressionInterpretParser:规则解析器
App:客户端
具体解析规则类:
AddExpression
- //加法
- public class AddExpression implements Expression{
-
- private Expression num1Expression; //第一个加数
- private Expression num2Expression; //第二个加数
-
- public AddExpression(Expression num1Expression, Expression num2Expression){
- this.num1Expression = num1Expression;
- this.num2Expression = num2Expression;
- }
- @Override
- public int interpret() {
- return num1Expression.interpret() + num2Expression.interpret();
- }
- @Override
- public String toString() {
- return "+";
- }
- }
SubExpression
- //减法
- public class SubExpression implements Expression{
-
- private Expression num1Expression; //第一个减数
- private Expression num2Expression; //第二个减数
-
- public SubExpression(Expression num1Expression, Expression num2Expression){
- this.num1Expression = num1Expression;
- this.num2Expression = num2Expression;
- }
- @Override
- public int interpret() {
- return num1Expression.interpret() - num2Expression.interpret();
- }
- @Override
- public String toString() {
- return "-";
- }
- }
MulExpression
- //乘法
- public class MulExpression implements Expression{
-
- private Expression num1Expression; //第一个乘数
- private Expression num2Expression; //第二个乘数
-
- public MulExpression(Expression num1Expression, Expression num2Expression){
- this.num1Expression = num1Expression;
- this.num2Expression = num2Expression;
- }
-
- @Override
- public int interpret() {
- return num1Expression.interpret() * num2Expression.interpret();
- }
- @Override
- public String toString() {
- return "*";
- }
- }
DivExpression
- //乘法
- public class DivExpression implements Expression{
-
- private Expression num1Expression; //第一个除数
- private Expression num2Expression; //第二个除数
-
- public DivExpression(Expression num1Expression, Expression num2Expression){
- this.num1Expression = num1Expression;
- this.num2Expression = num2Expression;
- }
- @Override
- public int interpret() {
- return num1Expression.interpret() / num2Expression.interpret();
- }
- @Override
- public String toString() {
- return "/";
- }
- }
ExpressionInterpretParser
-
- public class ExpressionInterpretParser {
-
-
- private LinkedList
list = new LinkedList<>(); -
- private boolean isSymbol(String sy){
- return "+".equals(sy) || "-".equals(sy) || "*".equals(sy)|| "/".equals(sy);
- }
-
- private Integer operation(Expression num1, Expression num2, String symbol){
- if("+".equals(symbol)){
- return new AddExpression(num1,num2).interpret();
- }else if("-".equals(symbol)){
- return new SubExpression(num1,num2).interpret();
- }else if("*".equals(symbol)){
- return new MulExpression(num1,num2).interpret();
- }else if("/".equals(symbol)){
- return new DivExpression(num1,num2).interpret();
- }
-
- return null;
-
- }
- public void parse(String express){
- String[] items = express.split(" ");
- for (String item : items) {
- if(!this.isSymbol(item)){
- list.addLast(new NumExpression(item));
- System.out.println("入栈参数:" + item);
- }else{
- System.out.println("运算符:" + item);
- Expression num1 = list.removeFirst();
- Expression num2 = list.removeFirst();
- Integer ret = this.operation(num1, num2, item);
- if(ret == null){
- System.out.println("表达式解析异常,无法运算");
- return;
- }
- this.list.push(new NumExpression(ret));
- System.out.println("运算结果再入栈:" + ret);
- }
- }
-
- if(list.size() == 1){
- System.out.println("表达式运算结果:" + list.removeFirst());
- }
- }
- }
App
- public class App {
- public static void main(String[] args) {
- new ExpressionInterpretParser().parse("1 2 3 4 5 + - * /");
- }
- }
结果:
- 入栈参数:1
- 入栈参数:2
- 入栈参数:3
- 入栈参数:4
- 入栈参数:5
- 运算符:+
- 运算结果再入栈:3
- 运算符:-
- 运算结果再入栈:0
- 运算符:*
- 运算结果再入栈:0
- 运算符:/
- 运算结果再入栈:0
- 表达式运算结果:0
解析
加减乘除规则解析类,实现+-*/四则运算逻辑,将计算出结果重新入队列,参与后续计算。
一些规则引擎解析
一些确定语法表达式需要解析时
一些重复出现的问题可以用一种简单的语言来进行表达。
优点
语法由很多类表示,容易改变及扩展,新增表达式时,只需要添加新的表达式实现类即可,“开闭原则”。
缺点
当语法规则数目太多时,增加系统复杂度
Spring自带了SpEl表达式
- public class SpringELTest {
-
- public static void main(String[] args) {
- SpelExpressionParser parser = new SpelExpressionParser();
- Expression expression = parser.parseExpression("(((1+2)-3) *4) / 5 ");
- System.out.println(expression.getValue());
- }
- }
类体系:
解析体系类:ExpressionParser
- public interface ExpressionParser {
- Expression parseExpression(String expressionString) throws ParseException;
- Expression parseExpression(String expressionString, ParserContext context) throws ParseException;
- }
解析器实现类:SpelExpressionParser
- public class SpelExpressionParser extends TemplateAwareExpressionParser {
-
- @Override
- protected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {
- return new InternalSpelExpressionParser(this.configuration).doParseExpression(expressionString, context);
- }
-
- }
父类解析器
- public abstract class TemplateAwareExpressionParser implements ExpressionParser {
-
- private Expression parseTemplate(String expressionString, ParserContext context) throws ParseException {
- if (expressionString.isEmpty()) {
- return new LiteralExpression("");
- }
-
- Expression[] expressions = parseExpressions(expressionString, context);
- if (expressions.length == 1) {
- return expressions[0];
- }
- else {
- return new CompositeStringExpression(expressionString, expressions);
- }
- }
-
- }
解析之后结果对象:Expression
- public interface Expression {
- //表达式规则
- String getExpressionString();
- //解析完后结果
- @Nullable
- Object getValue() throws EvaluationException;
-
- }
解析器模式在特定领域,特定场景下才使用,相对其他模式来说,使用频率不高得设计模式啦。
最后来总结一下:
解析器模式的本质:分离实现,解释执行。