一、设计模式
GOF 设计模式是面向对象设计中常见问题的可复用解决方案,通过 23 种经典模式 提供了一套标准化的设计思路,用于解决软件设计中反复出现的架构和交互问题。其核心特点包括:
-
经验驱动:源于实际项目的经验总结,非理论推导。
-
抽象化:以接口和组合替代硬编码依赖,提升灵活性。
-
解耦:分离对象创建、结构组装和行为协作,降低耦合。
1.0、设计模式原则(SOLID)
-
单一职责原则(Single Responsibility Principle)
一个类应该只有一个发生变化的原因。
-
开闭原则(Open-Closed Principle, OCP)
软件实体(类、模块、函数等)应该对扩展开放,对修改封闭。这意味着应该能够在不修改现有代码的情况下,让软件的行为发生变化(通常通过添加新代码来完成)。
-
里氏替换原则(Liskov Substitution Principle)
所有引用基类的地方必须能透明地使用其子类的对象。
-
接口隔离原则(Interface Segregation Principle)
1、每个接口中不存在子类用不到却必须实现的方法,如果不然,就要将接口拆分。
2、使用多个隔离的接口,比使用单个接口(多个接口方法集合到一个的接口)要好。 -
依赖倒置原则(Dependence Inversion Principle)
1、上层模块不应该依赖底层模块,它们都应该依赖于抽象。
2、抽象不应该依赖于细节,细节应该依赖于抽象。
3、面向接口编程,依赖于抽象而不依赖于具体。
1.1、创建型模式(5 种)
目标: 解耦对象创建,提供灵活的对象实例化机制。
创建型模式 | JDK 应用示例 | 实现方式与作用 |
---|---|---|
单例模式 | java.lang.Runtime java.awt.Desktop | 饿汉式(静态初始化)或懒汉式(双重检查锁),确保全局唯一实例(如运行时环境管理)。 |
工厂模式 | java.util.Calendar#getInstance() java.text.NumberFormat#getInstance() | 通过静态方法隐藏对象创建细节,按参数返回不同子类实例(如日期格式化器)。 |
抽象工厂模式 | javax.xml.parsers.DocumentBuilderFactory | 定义接口创建一组相关对象(如 XML 解析器工厂生成 DocumentBuilder 和 SchemaFactory)。 |
建造者模式 | java.lang.StringBuilder java.util.stream.Stream.Builder | 分步构造复杂对象(如字符串拼接、流构建),避免构造函数参数爆炸。 |
原型模式 | java.lang.Cloneable 接口 | 通过 clone() 方法复制对象(如 ArrayList 的浅拷贝),减少重复创建开销。 |
1.2、结构型模式(7 种)
目标: 组合对象或类,形成更大结构的灵活方案,不破坏原有结构。
结构型模式 | JDK 应用示例 | 实现方式与作用 |
---|---|---|
适配器模式 | java.util.Arrays#asList() java.io.InputStreamReader | 转换接口兼容性(如数组转列表、字节流转字符流),通过包装对象实现接口适配。 |
装饰器模式 | java.io.BufferedInputStream java.util.Collections#unmodifiableList() | 动态扩展功能(如缓冲读写、集合不可变化),通过嵌套包装对象叠加行为。 |
代理模式 | java.lang.reflect.Proxy | 动态代理控制访问(如 AOP 切面),拦截方法调用并增强逻辑(权限校验、日志等)。 |
外观模式 | java.net.URL (封装网络连接细节) | 简化复杂子系统调用(如 URL 统一处理协议、域名解析和流操作),日志框架SLF4J。 |
桥接模式 | JDBC 驱动接口与实现类(如 java.sql.Driver 和 com.mysql.jdbc.Driver ) | 分离抽象与实现(如数据库驱动适配不同厂商),通过接口与实现类独立扩展。 |
组合模式 | java.awt.Container#add(Component) javax.swing.JTree | 统一处理树形结构(如 GUI 组件嵌套),叶子节点与容器节点共享同一接口。 |
享元模式 | java.lang.Integer#valueOf() java.util.Collections#emptyList() | 共享细粒度对象(如缓存 -128~127 的 Integer、空集合),减少内存占用。 |
1.3、行为型模式(11 种)
目标: 优化对象间交互与职责分配,定义通信流程和算法协作。
行为型模式 | JDK 应用示例 | 实现方式与作用 |
---|---|---|
策略模式 | java.util.Comparator java.util.Arrays#sort(T[], Comparator) | 封装算法族(如排序规则),运行时动态切换策略(Comparator 定义不同排序逻辑)。 |
模板方法模式 | java.io.InputStream ( read() 调用 read(byte[], int, int) ) | 定义算法骨架(如 IO 读取流程),子类重写特定步骤(如 read() 实现具体读取逻辑)。 |
观察者模式 | java.util.Observable java.util.Observer java.beans.PropertyChangeSupport | 订阅-通知机制(如事件监听),主题状态变化时自动通知观察者。 |
迭代器模式 | java.util.Iterator java.util.Enumeration | 统一遍历集合元素(如 List 、Set ),隐藏底层数据结构差异。 |
责任链模式 | java.util.logging.Logger (日志级别过滤) | 请求沿链传递(如日志处理器按级别过滤),每个节点决定处理或传递。 |
命令模式 | java.lang.Runnable javax.swing.Action | 封装请求为对象(如线程任务、GUI 操作),支持撤销、重做和队列管理。 |
备忘录模式 | java.io.Serializable (序列化实现状态保存) | 捕获对象内部状态(如对象持久化),支持回滚或恢复。 |
状态模式 | java.util.Iterator ( ArrayList.Itr 与 HashMap.EntryIterator ) | 对象行为随状态改变(如迭代器在不同集合中的遍历逻辑),通过状态类分离条件分支。 |
访问者模式 | javax.lang.model.element.ElementVisitor (注解处理器) | 解耦数据结构与操作(如 AST 遍历),通过 Visitor 接口扩展新操作而不修改元素类。 |
中介者模式 | java.util.concurrent.Executor (线程池任务调度) | 集中管理对象交互(如线程任务分配),减少组件间直接依赖。 |
解释器模式 | java.util.regex.Pattern (正则表达式解析) | 定义语法规则(如正则匹配),通过解释器解析和执行表达式(JDK 中较少直接使用,更多见于框架或 DSL 场景)。 |
二、JDK 中设计模式的应用特点
-
性能优先:
-
接口与实现解耦:
- 工厂模式(
Calendar
)、桥接模式(JDBC)隐藏底层实现细节,支持扩展。 - 代理模式(动态代理)分离调用逻辑与具体实现。
- 工厂模式(
-
功能动态扩展:
- 装饰器模式(IO 流嵌套)通过组合而非继承增强功能。
- 策略模式(
Comparator
)运行时切换算法逻辑。
-
行为标准化:
- 迭代器模式(
Iterator
)统一集合遍历接口。 - 模板方法模式(
InputStream
)固定流程框架,子类定制细节。
- 迭代器模式(
三、典型场景与源码分析
案例 1:装饰器模式(BufferedInputStream
)
java">// 基础组件:FileInputStream
InputStream raw = new FileInputStream("xiaolingting.txt");
// 装饰器:添加缓冲功能
InputStream buffered = new BufferedInputStream(raw);
// 再次装饰:添加解压功能(假设 GZIPInputStream 是另一装饰器)
InputStream gzip = new GZIPInputStream(buffered);
- 作用:逐层包装,动态叠加缓冲、解压等功能,避免继承导致的类爆炸。
案例 2:策略模式(Arrays.sort()
)
java">Arrays.sort(users, (u1, u2) -> u1.getAge() - u2.getAge()); // 自定义 Comparator
- 作用:将排序算法(如年龄比较)封装为策略对象,灵活替换不同比较逻辑。
案例 3:责任链模式(日志处理)
java">Logger logger = Logger.getLogger(Xiaolingting.Class);
logger.setLevel(Level.WARNING);
// 日志信息级别低于 WARNING 时,责任链中的处理器将忽略该消息
logger.log(Level.INFO, "This message will be filtered");
- 作用:日志消息依次经过各级处理器(如控制台输出、文件记录),根据级别决定是否处理。
四、总结
JDK 广泛运用设计模式解决代码复用、扩展性和结构优化问题:
- 高频模式:工厂、单例、装饰器、适配器、迭代器等,注重接口抽象与功能扩展。
- 低频模式:解释器、访问者等,更多用于特定领域(如编译器、复杂业务规则)。