讲师中心 微信公众号
AI工具推荐 视频效率加速

Java面试——常见的设计模式及其实战应用

冬枫大大_4838

冬枫大大_4838

发布时间:2026-01-06 05:11:25

|

884人浏览过

|

来源于php中文网

原创

单例模式中饿汉式线程安全但可能浪费资源,懒汉式需双重检查锁+volatile防止重排序;工厂模式按复杂度递进选择,观察者模式应弃用Java内置类而用自定义事件总线。

java面试——常见的设计模式及其实战应用

单例模式:饿汉式 vs 懒汉式,线程安全怎么选

单例不是写个 static final 就完事。饿汉式在类加载时就初始化实例,天然线程安全,但可能浪费资源;懒汉式延迟加载,但不加同步会出问题——new Singleton() 不是原子操作,可能返回半初始化对象。

推荐用双重检查锁(DCL),但必须给实例字段加 volatile,否则 JVM 指令重排序会导致其他线程看到未构造完成的对象:

public class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton(); // volatile 禁止此处重排序
                }
            }
        }
        return instance;
    }
}
  • 别用 Runtime.getRuntime() 或 System.getSecurityManager() 这类“伪单例”,它们不是你控制的生命周期
  • Spring 的 @Scope("singleton") 是容器级单例,和 JVM 级单例不是一回事,别混为一谈
  • 测试时如果单例依赖了外部状态(如数据库连接),记得在 @AfterEach 清理或用 reset() 方法,否则测试间会污染

工厂模式:简单工厂、工厂方法、抽象工厂,什么时候该升级

简单工厂(一个静态方法返回不同子类)适合产品种类少、不常变的场景,比如日志类型:LoggerFactory.getLogger("file")。但它违反开闭原则——新增日志类型就得改工厂类。

工厂方法把创建逻辑下放到子类,比如 PaymentService 接口有 createProcessor(),支付宝实现返回 AlipayProcessor,微信实现返回 WechatProcessor。这样新增支付渠道只需加新子类,不用动原有代码。

立即学习“Java免费学习笔记(深入)”;

抽象工厂用于“产品族”场景,比如跨平台 UI 组件:Windows 工厂返回 WinButton + WinCheckbox,Mac 工厂返回 MacButton + MacCheckbox。一旦开始支持深色模式、无障碍组件,抽象工厂结构更容易扩展。

向企业微信发送消息
向企业微信发送消息

严格按照企业微信文档规范,支持文本、markdown、markdown_v2、图片、图文等多种消息类型的发送技能。

下载
  • 别为了模式而模式。如果只有两个实现且长期稳定,直接用策略模式 + Map<string strategy></string> 更轻量
  • Spring 的 BeanFactory 是抽象工厂的典型应用,但你写的业务工厂类不需要继承 FactoryBean,除非要干预 Bean 实例化过程
  • 工厂类里别做复杂逻辑(比如读配置、连 DB),应只负责“new”和参数组装;重活交给 Builder 或 Service

观察者模式:Java 内置 Observer 已废弃,现在怎么写

java.util.Observer 和 Observable 在 JDK 9 就标记为 @Deprecated,因为设计僵硬:被观察者必须继承 Observable,无法组合复用,且通知顺序不可控、异常会中断后续监听。

现代写法是自定义接口 + 显式注册管理,核心是解耦和可控性:

public interface EventListener<T> {
    void onEvent(T event);
}
public class EventBus {
    private final Map<Class<?>, List<EventListener<?>>> listeners = new ConcurrentHashMap<>();
    public <T> void register(Class<T> eventType, EventListener<T> listener) {
        listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()).add(listener);
    }
    public <T> void post(T event) {
        List<EventListener<?>> list = listeners.get(event.getClass());
        if (list != null) {
            list.forEach(l -> ((EventListener<T>) l).onEvent(event));
        }
    }
}
  • 别用 ArrayList 存监听器列表——并发修改会抛 ConcurrentModificationException,CopyOnWriteArrayList 更稳妥
  • 事件对象建议用不可变类(final 字段 + 无 setter),避免监听器中途篡改影响其他监听器
  • 如果事件需要异步处理(如发短信、写日志),别在 post() 里直接线程池提交,应由监听器自己决定同步/异步,否则难以测试和调试

装饰器模式:IO 流是经典,但 Spring AOP 其实也是它

BufferedInputStream 包一层 FileInputStream,GZIPInputStream 再包一层,这就是装饰器:不改变原始对象,通过组合动态添加行为。关键点是装饰器和被装饰对象实现同一接口(InputStream)。

Spring 的 @Transactional、@Cacheable 表面看是代理,底层本质也是装饰器思想——生成一个代理对象,在调用目标方法前后插入事务开启/提交、缓存读写等逻辑,而业务 Service 类完全 unaware。

  • 装饰器类名别叫 XXXDecorator,容易和 GUI 装饰混淆;用 Buffering、Retrying、Logging 这类动名词更直观
  • 避免嵌套过深。三层以上装饰(如 Logging(Retrying(Buffering(FileInputStream))))会让堆栈难读、性能下降,可考虑用 Builder 组装或配置化开关
  • 如果装饰逻辑涉及状态(如重试次数、缓冲区大小),确保每个装饰器实例是独立的,别用 static 变量共享状态,否则多线程下会串数据

模式本身不难,难的是判断“这里到底需不需要模式”。过度设计比不用模式更危险——比如一个只有两个分支的 if 判断,硬套策略模式反而让代码更绕。真正该花时间的,是识别出那些未来大概率会变、且变化方向明确的点,再决定引入哪层抽象。

热门AI工具

更多
超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

二狗PPT
二狗PPT Hot

一款AI演示文稿工具,主要用于专为中式职场打造的AI PPT生成工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

UP简历
UP简历 Hot

一款AI办公效率工具,主要用于基于AI技术的免费在线简历制作工具,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

相关专题

更多
spring框架介绍
spring框架介绍

本专题整合了spring框架相关内容,想了解更多详细内容,请阅读专题下面的文章。

2191

2025.08.06

Java Spring Security 与认证授权
Java Spring Security 与认证授权

本专题系统讲解 Java Spring Security 框架在认证与授权中的应用,涵盖用户身份验证、权限控制、JWT与OAuth2实现、跨站请求伪造(CSRF)防护、会话管理与安全漏洞防范。通过实际项目案例,帮助学习者掌握如何 使用 Spring Security 实现高安全性认证与授权机制,提升 Web 应用的安全性与用户数据保护。

417

2026.01.26

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

674

2025.10.23

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3048

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

4309

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3689

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

386

2026.01.19

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

4687

2023.07.18

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

80

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn