鸣谢:《大话设计模式》
简介
是一种行为型设计模式,用于定义一门语言的语法,并提供一个解释器来解释该语法中的表达式。它允许你将语言中的句子表示为一个抽象语法树,并定义一个解释器来解释这棵树。
主要组成部分:
- 抽象表达式(Abstract Expression):定义一个抽象接口,包含解释操作的方法。
- 终结符表达式(Terminal Expression):实现抽象表达式接口,表示文法中的终结符。
- 非终结符表达式(Non-terminal Expression):实现抽象表达式接口,表示文法中的非终结符,通常包含其他表达式。
- 上下文环境(Context):包含解释器之外的一些全局信息,可能影响解释器的行为。
- 客户端(Client):构建并配置具体的解释器,构建抽象语法树,并调用解释操作来解释语法。
工作流程
- 客户端创建和配置解释器,并构建抽象语法树。
-
客户端调用解释器的解释操作来解释抽象语法树。
-
解释器根据语法规则递归地解释抽象语法树的节点,最终得出结果。
例子
结构
代码
抽象表达式(Abstract Expression)
/**
* @author: lpy
* @Date: 2023/11/06
*/
public interface Interpreter {
int interpret();
}
终结符表达式(Terminal Expression)
/**
* @author: lpy
* @Date: 2023/11/06
* @desc: 终结符表达式
*/
public class NumberExpression implements Interpreter{
private int number;
public NumberExpression(int number){
this.number = number;
}
@Override
public int interpret() {
return number;
}
}
非终结符表达式(Non-terminal Expression)
/**
* @author: lpy
* @Date: 2023/11/06
* @desc: 非终结符表达式
*/
public class AddExpression implements Interpreter{
private Interpreter left;
private Interpreter right;
public AddExpression(Interpreter left, Interpreter right){
this.left = left;
this.right = right;
}
@Override
public int interpret() {
return left.interpret()+right.interpret();
}
}
上下文环境(Context)
/**
* @author: lpy
* @Date: 2023/11/06
*/
public class Context {
private String input;
public Context(String input){
this.input = input;
}
public String getOutput(){
return this.input;
}
}
客户端(Client)
/**
* @author: lpy
* @Date: 2023/11/06
*/
public class Client {
public static void main(String[] args) {
String input = "1 + 2 + 3";
Context context = new Context(input);
AddExpression addExpression = new AddExpression(
new NumberExpression(1),
new AddExpression(
new NumberExpression(2), new NumberExpression(3)
)
);
int res = addExpression.interpret();
System.out.println("解析结果:"+res);
}
}
应用
解释器模式适用场景 : 某个 特定类型问题 发生频率 足够高 ;
日志处理 : 使用 脚本语言 或 编程语言 处理日志时 , 有很多服务 会产生 大量的日志 , 需要 对日志进行解析 , 生成报表 ;
各个服务的日志格式不同 , 数据中的要素相同 , 这种情况下 , 通过程序解决上述问题 , 主要的解决方案就是使用解释器模式 ;
日常项目中 , 解释器模式使用情况很少 ;
解释器一般是 开源包 , 如 Express4J , JEP ;
原文链接:https://blog.csdn.net/shulianghan/article/details/119752572
- 编程语言解释器:解释器模式可用于构建编程语言解释器,如解释器可以解释脚本语言、查询语言或规则引擎中的代码。
-
正则表达式引擎:正则表达式的解释和匹配过程可以通过解释器模式实现。
-
自然语言处理:在自然语言处理中,解释器可用于分析和理解自然语言中的句子结构、语法和语义。
-
数学表达式求值:解释器可用于构建数学表达式求值引擎,用于计算数学表达式的结果。
-
配置文件解释:解释器可用于解释配置文件,将配置信息转化为系统参数或操作。
-
图像处理:在图像处理中,解释器可以解释和处理图像文件的格式和内容。
-
规则引擎:规则引擎通常使用解释器模式来解释和执行规则集。
-
音乐符号处理:在音乐编写软件中,解释器可用于解释音乐符号和生成音乐。
解释器模式与适配器模式
解释器模式与适配器模式 : 这两个模式类似 , 但是略有不同 ;
- 适配器模式 : 不需要 预先知道 适配器的 规则 ;
-
解释器模式 : 需要 预先将规则写好 , 根据规则执行解释 ;
解释器模式优缺点
-
优点:
- 可扩展性:可以方便地添加新的文法规则和表达式。
-
易于维护:将语法规则和解释操作分开,使代码更易维护。
-
可重用性:已有的表达式可以被重复使用。
-
缺点:
- 复杂性:复杂的文法可能需要大量的表达式类,增加了系统的复杂性。
-
性能:解释器模式可能会引入性能开销,因为需要递归解释抽象语法树的节点。
7 大设计原则
不能全部遵守 , 也不能不遵守 , 注意平衡 功能 和 系统复杂度 , 找到最合适的一个点 ;
- 单一职责原则(Single Responsibility Principle - SRP):
这个原则规定一个类应该只有一个改变的理由,也就是说,一个类应该只有一个单一的职责。这有助于保持类的简单性和可维护性,因为每个类只需关注一个特定的功能。
- 开放-封闭原则(Open-Closed Principle - OCP):
开放-封闭原则要求系统中的软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着当需要添加新功能时,应该通过扩展现有代码来实现,而不是修改原有代码。
- 里氏替换原则(Liskov Substitution Principle - LSP):
里氏替换原则规定,子类应该能够替换其父类,而不会影响程序的正确性。也就是说,子类应该继承父类的行为,但可以扩展或修改该行为,但不应该改变父类的行为。
- 接口隔离原则(Interface Segregation Principle - ISP):
接口隔离原则要求一个类不应该强迫其客户端依赖于它们不需要的接口。应该根据客户端的需求定义小而精确的接口,而不是大而笨重的接口。
- 依赖倒置原则(Dependency Inversion Principle - DIP):
依赖倒置原则要求高级模块不应该依赖于低级模块,它们都应该依赖于抽象。具体来说,这意味着应该通过抽象接口或抽象类来定义模块之间的依赖关系,而不是直接依赖于具体实现。
- 迪米特法则(Law of Demeter - LoD):
如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用。如果其中一个类需要调用另一个类的某一个方法的话,可以通过第三者转发这个调用。
- 合成复用原则(Composite Reuse Principle - CRP):
合成复用原则鼓励通过组合(合成)已有的类来实现新功能,而不是通过继承现有的类。这样可以降低系统的耦合度,并且更加灵活。
源码位置
全部源码github.com/xs-alpha/designPattern
参考文献
- 《大话设计模式》
-
慕课视频《Java设计模式精讲 Debug方式+内存分析》
如有内容侵权,麻烦联系博主删除