Java 单例模式核心是保证一个类仅有一个实例,常用实现有 5 种:饿汉式(类加载就创建,天生线程安全)、懒汉式(用时创建,基础版非线程安全)、双重检查锁(DCL,加 volatile 修饰,兼顾性能与线程安全)、静态内部类(懒加载 + 线程安全,最优方案之一)、枚举单例(最简单,防反射 / 序列化破坏)。 应用场景有工具类、线程池、配置管理器等。注意事项:要规避反射、序列化破坏单例;高并发场景必须用线程安全实现;不要滥用单例,否则会增加代码耦合,不利于单元测试,枚举单例是生产环境最推荐的方案。
观察者模式是一对多依赖,主题(被观察者)状态变化时,所有观察者自动收到通知并更新。Java 中可通过 Observable 类、Observer 接口实现,也可用自定义监听列表实现。 优点是解耦主题与观察者,符合开闭原则;缺点是观察者过多时通知效率低,且循环依赖会导致崩溃。它和发布 - 订阅模式的区别:前者是直接通信,后者通过中间件解耦;和中介者模式区别:观察者是一对多联动,中介者统一管理多对象交互;和事件监听模式本质一致,事件监听是它的具体落地场景。
工厂方法和抽象工厂都属于创建型模式,核心区别是生产产品的粒度不同。工厂方法模式针对单一产品,定义一个创建产品的接口,不同子类工厂生产不同的单一产品,遵循单一职责。 抽象工厂模式针对产品族,一个工厂可以生产一系列相关的产品,比如家电工厂能生产空调、冰箱、洗衣机。简单说:工厂方法造单个对象,抽象工厂造一组对象。工厂方法适合产品种类单一的场景,抽象工厂适合多品类、关联产品的创建,扩展性更强,但结构更复杂。
代理模式是给对象找一个代理对象,控制原对象的访问,解决直接访问对象的开销、权限、日志等问题。有三种实现:静态代理(手动写代理类,简单但灵活性差)、JDK 动态代理(基于接口,运行时生成代理类)、CGLIB 动态代理(基于继承,可代理无接口的类)。 适用场景:远程代理、日志记录、权限控制、事务管理。和装饰器模式区别:代理是控制访问,不增强功能;装饰器是动态增强功能,不改变访问权限,两者核心目的完全不同。
装饰器模式是动态给对象添加额外功能,不改变原类结构,遵循开闭原则。实现核心:定义抽象组件接口,具体组件实现基础功能,装饰器类实现该接口并持有组件对象,子类装饰器叠加功能。 比如 Java IO 就是经典实现,FileInputStream 是基础流,BufferedInputStream、DataInputStream 是装饰器,动态给流添加缓冲、数据读取功能。它通过组合的方式,在调用原对象方法前后添加逻辑,实现功能增强,比继承更灵活,可任意组合多个装饰器,避免类爆炸。
建造者模式用于创建复杂对象,把对象的构建和表示分离,分步组装属性。应用场景:需要创建属性多、可选参数多的对象,比如实体类、订单、电脑配置、MyBatis 的 SqlSessionFactory、StringBuilder 等。 和工厂模式区别:工厂模式关注创建产品本身,一步到位生成对象;建造者模式关注产品的组装过程,分步构建,可灵活调整对象的组成。简单说:工厂造成品,建造者一步步拼装成品,适合创建结构复杂、参数多样的不可变对象。
策略模式定义一组可互换的算法,封装每个算法,让它们独立切换。解决的是 if-else/switch 过多、算法难以扩展的问题,比如支付方式(微信、支付宝、银行卡)、排序算法切换。 应用时定义策略接口,不同实现类对应不同算法,上下文类持有策略对象调用方法。和状态模式区别:策略模式中策略相互独立、可随意替换,上下文不感知策略变化;状态模式中状态是流转的、有依赖关系,状态变化会影响上下文行为,两者核心逻辑完全不同。
桥接模式是将抽象与实现分离,让两者独立变化,通过组合关联,解决多维度变化导致的类爆炸问题。比如图形有圆形、方形,颜色有红、蓝,用继承会生成 4 个类,维度增加后类会指数级增长。 桥接模式把图形(抽象)和颜色(实现)分开定义,通过组合关联,一个图形类搭配任意颜色类,只需要 2+2=4 个基础类,新增维度只需单独加类,不用修改原有代码。它用组合替代继承,解耦两个变化维度,大幅减少类的数量,提升代码扩展性。
命令模式把请求封装成对象,让请求的发送者和接收者解耦。实现核心:定义命令接口,具体命令类绑定接收者,调用者持有命令对象执行命令。 工作原理:调用者发起命令,命令对象调用接收者的方法,无需知道接收者的具体逻辑。应用场景:菜单按钮、事务操作、任务调度,核心优势是支持请求排队、日志记录、撤销操作,比如文本编辑器的撤销 / 重做,就是用命令模式记录每一步操作,反向执行命令即可,让代码更灵活,易于扩展。
适配器模式是让不兼容的接口协同工作,像转接头一样做适配。解决的核心问题:系统需要使用一个类,但它的接口和现有系统不匹配;复用多个现存类,接口不统一无法协同。 分为类适配器(继承实现)和对象适配器(组合实现,推荐)。比如 Java 的 Arrays.asList(),把数组适配成 List 集合;旧系统的日志接口适配新日志框架。它不修改原有代码,符合开闭原则,让不兼容的组件无缝对接,提升代码复用性,减少改造原有接口的成本。
享元模式是共享细粒度对象,复用已有对象,避免重复创建,核心是区分内部状态(共享)和外部状态(独立)。应用场景:对象数量巨大、创建开销大、可共享的场景,比如 Java 的 String 常量池、Integer 缓存池、数据库连接池、线程池。 原理:用一个容器(Map)缓存创建过的对象,需要时先从容器获取,不存在再创建。这样大幅减少对象创建数量,降低内存占用,减少 GC 开销,提升系统性能。适合大量重复对象的场景,是 Java 底层优化的常用设计模式。
责任链模式把请求处理者连成一条链,请求依次传递,直到有处理者处理为止。原理:定义抽象处理者接口,每个具体处理者持有下一个处理者引用,请求到来时,自己能处理就处理,不能就传给下一个。 应用场景:过滤器、拦截器、审批流程(员工请假→经理→总监)、日志分级处理。核心优势:解耦请求发送者和处理者,可动态增删、调整处理者顺序,符合开闭原则,避免大量 if-else 判断,让请求处理逻辑更清晰、易于维护。
中介者模式用一个中介对象封装多个对象的交互,让对象之间不再直接引用,解决多对象耦合过深的问题。实现:定义中介者接口,具体中介者持有所有交互对象,对象之间的通信都通过中介者转发。 解决的问题:对象之间网状依赖,修改一个对象会影响所有关联对象,代码难以维护。比如聊天室(用户不直接聊天,通过服务器中介)、GUI 组件交互。核心作用是解耦多对象交互,把网状结构变成星型结构,降低耦合,让代码更易于扩展和维护。
外观模式是给复杂子系统提供一个统一入口,简化外部调用,也叫门面模式。实现很简单:创建一个外观类,封装子系统中多个复杂的接口和方法,对外只提供一个简洁的调用方法。 比如电脑开机,不需要手动调用 CPU、内存、硬盘的启动方法,只需要调用外观类的 start() 方法即可。Java 的 JDBC 工具类、Spring 的 JdbcTemplate 都是外观模式的应用。它不修改子系统,只是封装调用,降低使用成本,解耦外部与子系统,让代码更简洁易用。
组合模式把对象组合成树形结构,统一处理单个对象和组合对象,让用户对两者的使用一致。应用场景:存在层级、树形结构的场景,比如文件系统(文件夹 + 文件)、菜单(一级菜单 + 子菜单)、部门架构、XML/HTML 解析。 实现:定义抽象组件接口,叶子节点(单个对象)和组合节点(容器对象)实现该接口,组合节点持有子组件列表。用户不用区分是单个对象还是组合对象,直接调用统一方法,方便管理层次结构,简化遍历和操作。
模板方法模式定义一个算法的固定骨架,把可变步骤延迟到子类实现,父类控制整体流程,子类重写具体步骤。解决的核心问题:多个子类有相同的算法流程,只是部分步骤实现不同,避免重复代码。 比如 Java 的 AbstractList、Servlet 的 doGet/doPost,都是模板方法的应用。父类定义模板方法(final 修饰,防止子类重写),封装固定流程,子类只需要实现个性化步骤。它符合开闭原则,提升代码复用性,让流程统一、逻辑清晰,减少重复开发。
迭代器模式封装集合的遍历逻辑,提供统一的遍历接口,不用暴露集合的内部结构。实现:定义迭代器接口(hasNext、next),集合类实现 Iterable 接口,返回迭代器对象。 Java 的所有集合(List、Set、Map)都基于迭代器模式,不管是 ArrayList、LinkedList,都能用 iterator() 或增强 for 循环遍历。作用是解耦集合和遍历逻辑,让不同集合的遍历方式统一,用户不用关心集合底层是数组还是链表。它是集合框架的核心设计,提升了代码的通用性和可维护性。