从单例模式说起:Java 常见设计模式的理解与实践

文章目录

在 Java 后端开发中, 设计模式 几乎是绕不开的话题。
不论是日常业务开发、系统重构,还是技术面试,设计模式都会被反复提及。

但很多时候,我们停留在"知道名字、会背定义",却说不清楚:

  • 这个模式 为什么要用?
  • 什么时候用才合适?
  • 在真实项目中 到底解决了什么问题?

一、什么是 Java 中的单例模式(Singleton)

1️⃣ 定义

单例模式是一种创建型设计模式,其核心目标是:

保证一个类在 JVM 中只有一个实例,并提供一个全局访问点。

通俗理解就是:

  • 这个类只能创建一个对象
  • 对象由自己控制创建
  • 外部通过统一入口访问

二、Java 中常见的单例实现方式

1、饿汉式(线程安全)

java 复制代码
public class Singleton {
    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

优点

  • 实现简单
  • 天然线程安全

缺点

  • 类加载时就创建实例
  • 如果对象创建成本高,可能造成资源浪费

2、懒汉式(双重检查锁,推荐)

java 复制代码
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();
                }
            }
        }
        return instance;
    }
}

关键点说明:

  • volatile 防止指令重排
  • 双重 if 判断减少不必要的同步开销

这是企业级项目中非常常见的一种写法


3、静态内部类(最优雅)

java 复制代码
public class Singleton {
    private Singleton() {}

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

特点:

  • 懒加载
  • 线程安全
  • 无需显式加锁,性能好

在很多场景下,这是综合性最优的单例实现方式。


4、枚举单例(最安全)

java 复制代码
public enum Singleton {
    INSTANCE;
}

优点:

  • 天然防反射
  • 天然防反序列化
  • 《Effective Java》官方推荐

不足:

  • 不够灵活
  • 不适合复杂初始化逻辑

三、单例模式在真实项目中的使用场景

1️⃣ Spring 中的单例 Bean

java 复制代码
@Service
public class UserService {
}
  • Spring 默认 scope = singleton
  • 容器中只存在一个实例
  • 所有请求共享该对象

这其实是我们每天都在使用、却容易忽略的单例模式。


2️⃣ 数据库连接池 / 线程池

java 复制代码
DataSource dataSource;
ExecutorService executorService;

使用单例的原因很明确:

  • 创建成本高
  • 需要全局共享
  • 需要统一管理资源

频繁创建只会带来性能和稳定性问题。


3️⃣ 工具类 / 管理类

java 复制代码
LogManager
ConfigManager
RedisClient

例如:

  • Redis 客户端管理
  • MinIO Client
  • MQ Producer / Consumer 管理器

这些类通常:

  • 不保存业务状态
  • 被多个模块复用
  • 非常适合单例模式

4️⃣ JVM 级别资源

java 复制代码
Runtime.getRuntime();

典型代表包括:

  • Runtime
  • System
  • Logger

这些都是 JVM 级别的全局唯一资源。


四、单例模式的优缺点总结

✅ 优点

  • 减少对象创建,节省内存
  • 统一管理共享资源
  • 使用方便,全局可访问

❌ 缺点

  • 隐式依赖,不利于单元测试
  • 容易膨胀为"上帝类"
  • 多线程场景下实现复杂

单例模式不是银弹,关键在于是否用在合适的地方。


五、除了单例,还有哪些常见设计模式?

创建型模式

模式 使用场景
Singleton 全局唯一实例
Factory 封装对象创建
Abstract Factory 创建产品族
Builder 构建复杂对象
Prototype 对象复制

结构型模式

模式 使用场景
Proxy AOP、权限、事务
Decorator 功能增强
Adapter 接口不兼容
Facade 对外统一入口
Composite 树形结构

行为型模式

模式 使用场景
Strategy 不同算法切换
Template Method 固定流程,步骤可变
Observer 事件通知
Chain of Responsibility 过滤器、拦截器
State 状态机、流程流转

六、总结

  • 单例模式是最常见、也最容易被滥用的设计模式
  • 真正重要的不是"会写代码",而是"知道什么时候该用"
  • 设计模式的本质是:让系统更容易维护和扩展
相关推荐
旋律41412 分钟前
String、StringBuilder、StringBuffer:三个"字符串",到底区别在哪?
java·后端
一条泥憨鱼1 小时前
【Redis | 黑马点评】基于Redis的消息队列 | stream消息队列 源码解读
java·数据库·redis·缓存·lua
aibo8603081 小时前
基于 Spring Boot + Vue3 的博物馆藏品管理系统设计与实现
java·spring boot·后端
fanruitian1 小时前
python 进程 线程
java·前端·python
\光辉岁月/1 小时前
javaSE8-新特性-Stream&Option
java·stream·option
zzu123zsw1 小时前
把条件校验收敛到枚举接口:Spring Boot 统一断言模式与零污染异常切面工程化
java·spring boot·后端·架构设计
SL_staff1 小时前
计划系统落地难?从开发者视角重构执行入口体验
java·开源·全栈
鬼手点金1 小时前
单轮对话:最简单的 API 调用
java·服务器·前端·javascript·react.js·servlet·tomcat
牛牛牌蜡笔小新2 小时前
Java-常用类库
java·开发语言
Wang's Blog2 小时前
Java 项目实战: 交友项目 - MongoDB集群:概述
java·mongodb·交友