• Python之单例模式


    一、介绍

    单例模式是一种常用的软件设计模式,属于创建型模式。单例模式的核心结构就是系统中一个类只有一个实例,保证了在程序的不同位置都可以且仅可以取到同一个对象实例。

    应用场景:

    1.单例模式广泛应用于各种开发场景:

    游戏中需要有“场景管理器”这样一种东西,用来管理游戏场景的切换、资源载入、网络连接等等任务。这个管理器需要有多种方法和属性,在代码中很多地方会被调用,且被调用的必须是同一个管理器,否则既容易产生冲突,也会浪费资源

    2.一些资源管理器常常设计成单例模式:

    在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印机作业同时输出到打印机中。每台计算机可以有若干传真机卡,但是只应该有一个软件负责管理传真卡,以避免一个通信端口同时被两个请求同时调用。

    需要管理的资源包括软件内部资源,譬如,大多数的软件都有一个(甚至多个)属性(properties)文件存放系统配置。这样的系统应当由一个对象来管理一个属性文件。

    二、单例模式

    1、常用的单例模式

    class Singleton(object):
        _instance = None
    
        def __new__(cls, *args, **kwargs):
    
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls)
            return cls._instance
    
    
    s1 = Singleton()
    s2 = Singleton()
    print(s1 is s2)  # True

    属性共用的单例

    """
    上面的第一种写法,虽然创建的是同一个实例,
    但是属性是不共用的,因为每次__init__都会重新设置
    """
    class Singleton(object):
        _instance = None
    
        def __new__(cls, *args, **kwargs):
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls)
            return cls._instance
    
        def __init__(self, name, age):
            self.name = name
            self.age = age
    
    
    s1 = Singleton(name="小明", age=18)
    print(s1.name, s1.age)  # 小明 18
    
    s2 = Singleton(name="小红", age=17)  # 这里相当于是重新赋值了name和age,之后的name age都是这个值
    print(s2.name, s2.age)  # 小红 17
    
    print(s1 is s2)  # True
    
    
    """
    因此想要属性也共用,__init__也需要处理
    """
    class Singleton(object):
        _instance = None
        _initialized = False
    
        def __new__(cls, *args, **kwargs):
    
            if not cls._instance:
                cls._instance = super(Singleton, cls).__new__(cls)
            return cls._instance
    
        def __init__(self, name, age):
            if not Singleton._initialized:
                self.name = name
                self.age = age
                Singleton._initialized = True
    
    
    s1 = Singleton(name="小明", age=18)
    print(s1.name, s1.age)  # 小明 18
    
    s2 = Singleton(name="小红", age=17)
    print(s2.name, s2.age)  # 小明 18
    
    print(s1 is s2)  # True

    加锁的单例

    import time
    import threading
    
    
    class Singleton(object):
        lock = threading.RLock()  # 定义一把锁
        _instance = None
    
        def __new__(cls, *args, **kwargs):
            if cls._instance:
                return cls._instance  # 如果之前实例化过,没必要再次实例化,因为都是同一个实例
    
            with cls.lock:  # 避免当线程没有返回实例前,另一个线程也进来了,导致出现不止一个实例
                if not cls._instance:
                    cls._instance = super(Singleton, cls).__new__(cls)
                return cls._instance
    
    
    def task(arg):
        obj = Singleton()
        print(obj)
    
    
    for i in range(10):
        t = threading.Thread(target=task,args=(i,))
        t.start()
    
    
    time.sleep(10)
    obj = Singleton()

    2、函数单例装饰器

    def singleton(cls):
        _instance = {}
    
        def _singleton(*args, **kwargs):
            if cls not in _instance:
                _instance[cls] = cls(*args, **kwargs)
    
            return _instance[cls]
    
        return _singleton
    
    
    
    @singleton
    class A():
        def __init__(self, name):
            self.name = name
    
    a1 = A("ming")
    print(a1.name)  # ming
    
    a2 = A("dong")
    print(a2.name)  # ming

    3、类单例装饰器

    class Singleton(object):
        def __init__(self, cls):
            self._cls = cls
            self._instance = {}
    
        def __call__(self, *args, **kwargs):
            if self._cls not in self._instance:
                self._instance[self._cls] = self._cls(*args, **kwargs)
    
            return self._instance[self._cls]
    
    
    @Singleton
    class A():
        def __init__(self, name):
            self.name = name
    
    
    a1 = A("ming")
    print(a1.name)  # ming
    
    a2 = A("dong")
    print(a2.name)  # ming

    4、使用 metaclass 实现单例模式

    class Singleton(type):
        _instance = {}
    
        def __call__(cls, *args, **kwargs):
            if cls not in cls._instance:
                cls._instance[cls] = super(Singleton, cls).__call__(*args, **kwargs)
            return cls._instance[cls]
    
    
    class A(metaclass=Singleton):
        def __init__(self, name):
            self.name = name
    
    
    a1 = A("ming")
    print(a1.name)  # ming
    
    a2 = A("dong")
    print(a2.name)  # ming
  • 相关阅读:
    Android APK安装过程介绍
    Android Linux自带iptables配置IP访问规则
    海康视频监控---Demo
    Go之获取Windows下文件是否隐藏
    Go之go与channel组合使用
    Go并发编程(四)
    Go错误处理(二)
    Go面向对象(三)
    判断两端日期是否重合
    Sql分页存储过程
  • 原文地址:https://www.cnblogs.com/Zzbj/p/15779604.html
Copyright © 2020-2023  润新知