Python实现软件设计模式6:单例模式 Singleton Pattern
动机
- 针对某个类,为了保证系统中只创建一个示例,并且易于被访问(例如操作系统的任务管理器,软件的登陆注册界面)
- 自行创建这个实例,无法从外部创建这个实例,向系统提供这个实例
饿汉式单例 Java版本
在类加载的时候,就创建对象,如果后续得不到使用,可能会造成内存资源浪费
懒汉式单例 Java版本
只有第一次使用getInstance静态方法时,才会创建唯一的对象,不会导致系统资源浪费;但在多线程执行环境下,可能生成多个示例对象而不唯一。
懒汉式单例 与 双重检查锁定 Java版本
volatile关键字让Java虚拟机不要可以优化instance相关的代码。
单例模式小结
-
饿汉式单例:无需考虑多个线程同时访问的问题,调用速度和反应时间优于懒汉式单例,资源利用效率不及懒汉式单例,系统加载时间可能会比较长;
-
懒汉式单例:实现了延迟加载,但是 必须处理好多个线程同时访问的问题;需要通过双重检查锁定等机制进行控制,将导致系统性能受到一定影响;
内部静态类单例模式 Java版本
Python版本代码
class Logger(object):
__instance = None
def __init__(self):
raise RuntimeError('Call instance() instead')
@classmethod
def instance(cls):
if cls.__instance is None:
print('Creating new instance')
cls.__instance = super(Logger, cls).__new__(cls) # cls.__new__(cls)
return cls.__instance
# log = Logger() # 报错
log1 = Logger.instance()
print(log1)
log2 = Logger.instance()
print(log1 is log2)
def singleton(cls):
instances = {}
def getinstance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs) # 仅初始化1次生成一个唯一的对象
return instances[cls]
return getinstance
@singleton
class Country:
def __init__(self, name, area):
self.name = name
self.area = area
print(f"Country name: {self.name}, land area: {self.area} km^2.")
a = Country('China', 965)
b = Country('Japan', 75)
print(a == b) # True,因为 a 和 b 引用的是同一个实例
print(a.name, a.area)
print(b.name, b.area)