java解释器模式:自定义规则实现逻辑

1,058 阅读5分钟

image.png

这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战

迎来到今天的学习,今天我们一起来学习下应用场景很少,但很有意思的一种模式----解释器模式。多唠叨几句,我本月将会对java的设计模式精讲,欢迎点击头像,关注我的专栏,我会持续更新,加油!

系列文章:

设计模式之单例模式

设计模式之工厂模式

设计模式之建造者模式

设计模式之代理模式

设计模式之访问者模式

设计模式之适配器模式

设计模式之命令者模式

java状态模式 | 随时随地监控状态改变

java观察者模式 | 如何通知事物的变化

java备忘录模式 | 如何记录历史信息

java迭代器模式模式 | 如何对各个元素进行访问

java享元模式 | 如何共享对象

...持续更新中

话不多说,进入正题

解释器模式

解释器模式(Interpreter Pattern) 提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。

我们身边常会遇到的,比如规则引擎、正则表达式、SQL 解析等。我们要了解解释器的实现原理。思考如何通过更简洁的规则来表示复杂的逻辑。

官方是这样定义的:用于定义语言的语法规则表示,并提供解释器来处理句子中的语法。

  • 我理解过来的就是自定义一些规则,然后处理相应的逻辑。可以理解成,我来解释该规则,处理逻辑的过程就是解释的内容。

  • 在编程语言中,if-else 用作条件判断的语法,for 用于循环语句的语法标识。再比如,“我爱掘金”是一个中文句子,我们可以用名词、动词、形容词等语法规则来直观地描述句子。

我们下面看图

image.png

  • 上下文(Context):包含解释器全局的信息。

  • 抽象表达式(AbstractExpression):定义一个解释器有哪些操作,可以是抽象类或接口,同时说明只要继承或实现的子节点都需要实现这些操作方法。

  • 终结符表达式(TerminalExpression):用于解释所有终结符表达式:(比如解析c=a+b,a和b是终结符,解析a和b的解释器就是终结符表达式)

  • 非终结符表达式(NonterminalExpression):用于解释所有非终结符表达式:(比如c=a+b,“+"就是非终结符,解析“+”的解释器就是一个非终结符表达式)

我们用实际代码深入理解:

代码展示

我们创建一个逻辑与的解释器例子。简单来说,就是通过字符串名字来判断表达式是否同时存在,存在则打印 true,存在一个或不存在都打印 false。在下面的代码中,我们会创建一个接口 Expression 和实现 Expression 接口的具体类,并定义一个终结符表达式类 TerminalExpression 作为主解释器,再定义非终结符表达式类,这里 OrExpression、AndExpression 分别是处理不同逻辑的非终结符表达式。

//定义一个表达式
public interface Expression {

    //通过字符串名字来判断表达式是否同时存在,存在则打印 true,存在一个或不存在都打印 false。
    boolean interpreter(String con);
}


//终结符表达式类
public class TerminalExpression implements Expression{
    String data;
    public TerminalExpression(String data) {
        this.data = data;
    }
    @Override
    public boolean interpreter(String con) {
        if(con.contains(data)) {
            return true;
        } else {
            return false;
        }
    }
}


//非终结符表达式类(and)
public class AndExpression implements Expression {
    Expression expr1;
    Expression expr2;
    public AndExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }
    public boolean interpreter(String con) {
        return expr1.interpreter(con) && expr2.interpreter(con);
    }
}

//非终结符表达式类(or)
public class OrExpression implements Expression {
    Expression expr1;
    Expression expr2;
    public OrExpression(Expression expr1, Expression expr2) {
        this.expr1 = expr1;
        this.expr2 = expr2;
    }
    public boolean interpreter(String con) {
        return expr1.interpreter(con) || expr2.interpreter(con);
    }
}



//调用下
public class Client {
    public static void main(String[] args) {
        Expression person1 = new TerminalExpression("mick");
        Expression person2 = new TerminalExpression("mia");
        Expression isSingle = new OrExpression(person1, person2);
        Expression spike = new TerminalExpression("spike");
        Expression mock = new TerminalExpression("mock");
        Expression isCommitted = new AndExpression(spike, mock);
        System.out.println(isSingle.interpreter("mick"));
        System.out.println(isSingle.interpreter("mia"));
        System.out.println(isSingle.interpreter("max"));
        System.out.println(isCommitted.interpreter("mock, spike"));
        System.out.println(isCommitted.interpreter("Single, mock"));
    }
}


//输出
true
true
false
true
false

从上面代码中我们可以看到:在表达式范围内的单词能获得 true 的返回,没有在表达式范围内的单词则会获得 false 的返回。

也就是说,表达式解释器的解析逻辑放在了不同的表达式子节点中,这样就能通过增加不同的节点来解析上下文。

点明主旨: 所以说,解释器模式原理的本质就是对语法配备解释器,通过解释器来执行更详细的操作。

OK 代码部分就到这里,解释器模式很少使用,主要应用于 SQL 解析、符号处理引擎等场景中。所以大家只要理解就行。Spring spel表达式大家可以看看!

总结

我认为该模式,易于扩展。暂时没有发现其他优点

image.png

使用场景分析:

  • 当一个语言需要解释执行时。如 XML 文档中<>括号表示的不同的节点含义。

  • 当问题重复出现,且可以用一种简单的语言来进行表达时。比如,使用 if-else 来做条件判断语句,当代码中出现 if-else 的语句块时都统一解释为条件语句而不需要每次都重新定义和解释

弦外之音

感谢你的阅读,如果你感觉学到了东西,麻烦您点赞,关注。

我已经将本章收录在专题里,点击下方专题,关注专栏,我会每天发表干货,本月我会持续输入设计模式。

加油! 我们下期再见!