Python实现软件设计模式6:单例模式 Singleton Pattern

发布时间 2023-12-20 13:00:58作者: 爱吃砂糖橘的白龙

动机

  • 针对某个类,为了保证系统中只创建一个示例,并且易于被访问(例如操作系统的任务管理器,软件的登陆注册界面)
  • 自行创建这个实例,无法从外部创建这个实例,向系统提供这个实例

饿汉式单例 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)