目录
- 二十一、设计模式之解释器模式
- 能帮我们干什么?
- 主要解决什么问题?
- 优缺点
- 优点
- 缺点:
- 使用的场景
- 角色和职责
- 实现
- 解释器
- 总结
二十一、设计模式之解释器模式
所属类型 | 定义 |
---|---|
行为型 | 允许你定义一个语言并解释该语言中的表达式 |
能帮我们干什么?
主要解决什么问题?
主要解决的是对于一些固定文法构建一个解释句子的解释器。
何时使用:如果一种特定类型的问题发生的频率足够高,那么可能就值得将该问题的各个实例表述为一个简单语言中的句子。这样就可以构建一个解释器,该解释器通过解释这些句子来解决该问题。
优缺点
优点
1、可扩展性比较好,灵活。
2、增加了新的解释表达式的方式。
3、易于实现简单文法。
缺点:
1、可利用场景比较少。
2、对于复杂的文法比较难维护。
3、解释器模式会引起类膨胀。
4、解释器模式采用递归调用方法。
使用的场景
一种语法,主要用在编译器、规则引擎、正则表达式
角色和职责
- Context 解释器上下文环境类
用来存储解释器的上下文环境,包含解释器之外的一些全局信息,比如需要解释的文法等 - AbstractExpression 解释器抽象类,抽象表达式
这个接口为抽象语法树中所有节点所共享 - TerminalExpression 解释器具体实现类,终结符表达式
实现与文法中的终结符相关联的解释操作
一个句子中的每个终结符需要该类的一个实例 - NonterminalExpression 解释器具体实现类,非终结符表达式
对文法中的每一个规则R :: = RR…R都需要一个NonterminalExpression类。
为从R到R的每个符号都维护一个AbstractExpression类型的实例变量。
为文法中的非终结符实现解释操作。解释一般要递归地调用表示R到R的那些对象的解释操作。 - Client 客户
构建(或被给定)表示该文法定义的语言中一个特定的句子的抽象语法树。该抽象语法树由NonterminalExpression和TerminalExpression的实例装配而成。
调用解释操作。
实现
这种模式实现了一个表达式接口,该接口解释一个特定的上下文。这种模式被用在 SQL 解析、符号处理引擎等。
https://gitcode.net/k316378085/Java/-/tree/master/java/com/kongxiang/raindrop/dp/type/behavior/interpreter
解释器
如何解决:构建语法树,定义终结符与非终结符。
实现难度: ⭐️ ⭐️ ⭐️ ⭐️ ⭐️
public interface Expression {
public boolean interpret(String context);
}
public class TerminalExpression implements Expression {
private String data;
public TerminalExpression(String data){
this.data = data;
}
@Override
public boolean interpret(String context) {
if(context.contains(data)){
return true;
}
return false;
}
}
public class OrExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public OrExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) || expr2.interpret(context);
}
}
public class AndExpression implements Expression {
private Expression expr1 = null;
private Expression expr2 = null;
public AndExpression(Expression expr1, Expression expr2) {
this.expr1 = expr1;
this.expr2 = expr2;
}
@Override
public boolean interpret(String context) {
return expr1.interpret(context) && expr2.interpret(context);
}
}
public class InterpreterPatternDemo {
//规则:Robert 和 John 是男性
public static Expression getMaleExpression(){
Expression robert = new TerminalExpression("Robert");
Expression john = new TerminalExpression("John");
return new OrExpression(robert, john);
}
//规则:Julie 是一个已婚的女性
public static Expression getMarriedWomanExpression(){
Expression julie = new TerminalExpression("Julie");
Expression married = new TerminalExpression("Married");
return new AndExpression(julie, married);
}
public static void main(String[] args) {
Expression isMale = getMaleExpression();
Expression isMarriedWoman = getMarriedWomanExpression();
System.out.println("John is male? " + isMale.interpret("John"));
System.out.println("Julie is a married women? "
+ isMarriedWoman.interpret("Married Julie"));
}
}
总结
解释器模式为某个语言定义它的语法表示,并定义一个解释器用来处理这个语法。
语言:不仅仅指平时说的中、英、日、法等各种语言。从广义上来讲,只要是能承载信息的载体,我们都可以称之为“语言”,比如,古代的结绳记事、盲文、哑语、摩斯密码等。
一些应用提供了内建(Build-In)的脚本或者宏语言来让用户可以定义他们能够在系统中进行的操作。解释器模式的目的就是使用一个解释器为用户提供一个一门定义语言的语法表示的解释器,然后通过这个解释器来解释语言中的句子。
解释器模式的使用可以使你更容易地实现特定语言的解释和执行,尤其在处理自定义的领域特定语言(DSL)时非常有用。然而,解释器模式可能导致类的数量增加,因为每个语法规则都需要一个相应的表达式类。此外,解释器模式可能会对性能产生影响,特别是在处理复杂语法时。
总之,解释器模式适用于需要解释和处理特定语言或表达式的情况,它通过将语句表示为抽象语法树并提供解释器来执行解释。这有助于实现定制的语言处理逻辑。