单例模式是一种创建型设计模式, 其主要目的是确保一个类只有一个实例, 并提供一个全局访问点来访问该实例。
优点:
缺点:
饿汉式实现是在类定义时就创建单例对象,不管是否需要使用该对象。
public class Singleton {
// 在类加载时就创建好实例
private static Singleton instance = new Singleton();
// 私有化构造函数,防止外部实例化
private Singleton() {}
// 提供一个公共的静态方法返回实例
public static Singleton getInstance() {
return instance;
}
}
懒汉式实现是在需要时才创建实例。
public class Singleton {
// 声明一个静态的实例变量,但不初始化
private static Singleton instance;
// 私有化构造函数,防止外部实例化
private Singleton() {}
// 提供一个公共的静态方法返回实例
public static Singleton getInstance() {
// 检查实例是否已经被创建,如果没有,才进行实例化
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
以上实现不是线程安全的,在多线程高并发访问时,要使用双重检查锁定来实现线程安全。
public class Singleton {
// 声明一个 volatile 类型的静态变量,确保多线程下的可见性
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;
}
}
使用静态内部类实现单例模式是一种常见的方式,这种方法利用了类加载的特性来保证懒加载和线程安全。
public class Singleton {
// 私有化构造方法,防止外部实例化
private Singleton() {}
// 静态内部类,用于实现懒加载和线程安全
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 对外提供获取单例对象的方法
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
使用模块来实现饿汉式单例模式是一种简单而有效的方法。在 Python 中导入一个模块时,解释器会确保这个模块只被加载一次,因此可以利用这一点来实现单例模式。
# singleton.py
class Singleton:
pass
# 创建单例实例
singleton_instance = Singleton()
# main.py
from singleton import singleton_instance
# 使用单例实例
singleton_instance.some_attribute = "some_value"
使用装饰器可以实现懒汉式单例模式,实例在第一次被请求时才会被创建。
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 Singleton:
pass
# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()
使用类属性也可以实现懒汉式单例模式。
class Singleton:
_instance = None # 类属性用于存储单例实例
@classmethod
def get_instance(cls, value):
if not cls._instance:
cls._instance = cls(value)
return cls._instance
# 使用单例对象
singleton_instance1 = Singleton.get_instance()
singleton_instance2 = Singleton.get_instance()
也可以通过 new 方法来实现,同样是将实例对象存储到类属性中。
class Singleton:
_instance = None
def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()
使用元类可以更加灵活地控制类的创建过程,从而实现懒汉式单例模式。
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
pass
# 使用单例对象
singleton_instance1 = Singleton()
singleton_instance2 = Singleton()
在多线程高并发访问时,要使用双重检查锁定来实现线程安全。
from threading import Lock, Thread
class SingletonMeta(type):
_instances = {}
_lock = Lock()
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
with cls._lock:
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
pass
《设计模式的艺术》
单例设计模式 (refactoringguru.cn)
Python中的单例模式的几种实现方式的及优化 - 听风。 - 博客园 (cnblogs.com)