这是我参与8月更文挑战的第13天,活动详情查看:8月更文挑战
迎来到今天的学习,今天我们一起来学习下应用场景很少,但很有意思的一种模式----解释器模式。多唠叨几句,我本月将会对java的设计模式精讲,欢迎点击头像,关注我的专栏,我会持续更新,加油!
系列文章:
...持续更新中
话不多说,进入正题
解释器模式
解释器模式(Interpreter Pattern) 提供了评估语言的语法或表达式的方式,它属于行为型模式。这种模式实现了一个表达式接口,该接口解释一个特定的上下文。
我们身边常会遇到的,比如规则引擎、正则表达式、SQL 解析等。我们要了解解释器的实现原理。思考如何通过更简洁的规则来表示复杂的逻辑。
官方是这样定义的:用于定义语言的语法规则表示,并提供解释器来处理句子中的语法。
-
我理解过来的就是自定义一些规则,然后处理相应的逻辑。可以理解成,我来解释该规则,处理逻辑的过程就是解释的内容。
-
在编程语言中,if-else 用作条件判断的语法,for 用于循环语句的语法标识。再比如,“我爱掘金”是一个中文句子,我们可以用名词、动词、形容词等语法规则来直观地描述句子。
我们下面看图
-
上下文(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表达式大家可以看看!
总结
我认为该模式,易于扩展。暂时没有发现其他优点
使用场景分析:
-
当一个语言需要解释执行时。如 XML 文档中<>括号表示的不同的节点含义。
-
当问题重复出现,且可以用一种简单的语言来进行表达时。比如,使用 if-else 来做条件判断语句,当代码中出现 if-else 的语句块时都统一解释为条件语句而不需要每次都重新定义和解释
弦外之音
感谢你的阅读,如果你感觉学到了东西,麻烦您点赞,关注。
我已经将本章收录在专题里,点击下方专题,关注专栏,我会每天发表干货,本月我会持续输入设计模式。
加油! 我们下期再见!