单例模式

创建型模式

访问次数: 12

单例模式确保一个类只有一个实例,并提供一个全局访问点。

类图
classDiagram
    class Singleton {
        -instance: Singleton
        -Singleton()
        +getInstance() Singleton
        +operation()
    }
    Singleton --> Singleton : creates
源代码示例
// 懒汉式单例(线程不安全)
class Singleton {
    private static Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
    
    public void operation() {
        System.out.println("Singleton operation");
    }
}

// 懒汉式单例(线程安全)
class ThreadSafeSingleton {
    private static volatile ThreadSafeSingleton instance;
    
    private ThreadSafeSingleton() {}
    
    public static ThreadSafeSingleton getInstance() {
        if (instance == null) {
            synchronized (ThreadSafeSingleton.class) {
                if (instance == null) {
                    instance = new ThreadSafeSingleton();
                }
            }
        }
        return instance;
    }
}

// 饿汉式单例
class EagerSingleton {
    private static final EagerSingleton instance = new EagerSingleton();
    
    private EagerSingleton() {}
    
    public static EagerSingleton getInstance() {
        return instance;
    }
}
# 懒汉式单例(线程不安全)
class Singleton:
    _instance = None
    
    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
        return cls._instance
    
    def operation(self):
        print("Singleton operation")

# 懒汉式单例(线程安全)
import threading

class ThreadSafeSingleton:
    _instance = None
    _lock = threading.Lock()
    
    def __new__(cls):
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super().__new__(cls)
        return cls._instance

# 饿汉式单例(使用装饰器)
def singleton(cls):
    instances = {}
    def get_instance(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
        return instances[cls]
    return get_instance

@singleton
class EagerSingleton:
    def __init__(self):
        pass

# 使用示例
if __name__ == "__main__":
    s1 = Singleton()
    s2 = Singleton()
    print(s1 is s2)  # True
    s1.operation()
应用场景
当系统中只需要一个实例,且需要全局访问时。应用场景包括: 1)数据库连接池,确保整个应用程序共享同一个连接池实例,避免资源浪费 2)日志记录器,全局统一的日志管理,确保日志格式和输出的一致性 3)配置管理器,系统配置信息只需要加载一次,全局共享访问 4)缓存管理器,应用程序级别的缓存实例,提供统一的缓存服务 5)线程池管理器,系统级别的线程资源管理,避免创建过多线程池实例 6)应用程序上下文,Spring等框架中的应用上下文,管理Bean的生命周期
精选场景详解 —— 数据库连接池:全局唯一共享实例
问题背景

若每个模块各自 new 一个连接池,会造成连接数暴涨、配置不一致,甚至拖垮数据库。系统需要「全进程共用一个池」。

模式如何解决
选用单例模式:ConnectionPool 构造函数私有,通过 getInstance() 提供唯一实例。所有 DAO/Repository 都从该实例借还连接。 要点: 1)保证全局唯一,资源可控; 2)懒加载或饿汉式按启动成本选择; 3)多线程下需正确同步(双重检查、静态内部类或语言级单例)。 注意:单例会引入全局状态,测试时可配合接口 + 可替换实现,避免过度耦合。在分布式多进程中,「进程内单例」并不等于「集群唯一」,集群级唯一需另用分布式协调。
场景模型(角色映射)

将模式中的抽象角色映射到该业务领域的具体类:

classDiagram
    class ConnectionPool {
        -instance: ConnectionPool
        -connections: List~Connection~
        -ConnectionPool()
        +getInstance() ConnectionPool
        +borrow() Connection
        +release(conn: Connection)
    }
    class Connection {
        +open()
        +close()
        +execute(sql: String)
    }
    class OrderRepository {
        +findById(id: long) Order
    }
    class UserRepository {
        +findById(id: long) User
    }
    ConnectionPool --> ConnectionPool : getInstance
    ConnectionPool --> Connection
    OrderRepository --> ConnectionPool
    UserRepository --> ConnectionPool