• python的单例模式


    单例模式

    1、什么是单例模式

    单例模式指的是类实例化时,只产生单个实例化对象。

    实例化多个对象会产生不同的内存地址,单例可以让所有调用者,在调用类产生对象的情况下都指向同一份内存地址。

    例如:打开文件。

    单例的目的:为了减少内存的占用。

    2、产生单例模式的四种方法

    2.1 方法一:__new__

    借助类内部的__instance属性,将object.__new__()产生的对象赋值给它。

    如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回。

    如果cls._instance不为None,直接返回cls._instance

    这样就可以在实例化类时,保证使用的都是同一个对象。

    class Singleton:
    
        __instance = None
    
        def __new__(cls, *args, **kwargs):
            
            if not cls.__instance:
                cls.__instance = object.__new__(cls)
            return cls.__instance
    
        def __init__(self):
            self.a = 123
    
    
    s1 = Singleton()
    print(s1,id(s1))
    
    s2 = Singleton()
    print(s2,id(s2))
    
    """
    <__main__.Singleton object at 0x000001DA1999F9E8> 2036244019688
    <__main__.Singleton object at 0x000001DA1999F9E8> 2036244019688
    """
    

    2.2 方法二:metaclass

    通过metaclass属性指定元类,控制类的实例化对象的创建。

    元类指定单例类实例化时产生的对象为元类中的__instance属性对应的对象。

    这样就可以使单例类每次实例化都为单例。

    class Base(type):
        __instance = None
        
        def __call__(cls, *args, **kwargs):
            if not cls.__instance:
                cls.__instance = super(Base, cls).__call__(*args, **kwargs)
            return cls.__instance
    
    class Singleton(metaclass=Base):
        pass
    
    s1 = Singleton()
    s2 = Singleton()
    
    print(s1,id(s1))
    print(s2,id(s2))
    
    """
    <__main__.Singleton object at 0x0000021AB8B9BC50> 2313791585360
    <__main__.Singleton object at 0x0000021AB8B9BC50> 2313791585360
    """
    

    2.3 方法三:装饰器

    这也是方法1的升级(高级)版本。

    这是一种更pythonic,更elegant的方法,单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的。

    而装饰器使单例类每次都会返回一个单例对象罢了。

    # 普通装饰器
    def make_singleton(cls,*args,**kwargs):
        _instances = {}
        
        def singleton_class():
            if cls not in _instances:
                _instances[cls] = cls(*args,**kwargs)
            return _instances[cls]
    
        return singleton_class
    
    
    @make_singleton
    class Test:
        a = 1
    
    
    s1 = Test()
    s2 = Test()
    print(s1,id(s1))
    print(s2,id(s2))
    
    '''
    <__main__.Test object at 0x0000027515C614E0> 2701899732192
    <__main__.Test object at 0x0000027515C614E0> 2701899732192
    '''
    
    # 第二种装饰器(强行用lambda函数)
    def lambda_decorator(cls,*args,**kwargs):
        _instance = cls(*args,**kwargs)
        cls.__call__ = lambda _instance: _instance
        return _instance
    
    @lambda_decorator
    class Test:
        a = 1
    
    
    s1 = Test()
    s2 = Test()
    print(s1,id(s1))
    print(s2,id(s2))
    
    '''
    <__main__.Test object at 0x000002318C7F1550> 2411833791824
    <__main__.Test object at 0x000002318C7F1550> 2411833791824
    '''
    

    2.4 方法四:共享属性

    所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)。

    而恰好同一个类的所有实例天然拥有相同的行为(方法),所以只需要保证同一个类的所有实例具有相同的状态(属性)即可。

    所有实例共享属性的最简单最直接的方法就是让__dict__属性指向(引用)同一个字典(dict),这样就可以让实例之间共享属性了。

    这样做虽然对象并非真正的同一个对象(id不同),但是由于所有的对象属性与方法都相同,但也可以称作单例。

    class Base:
        _dic = {}
    
        def __new__(cls, *args, **kwargs):
            obj = super().__new__(cls,*args, **kwargs)
            obj.__dict__ = cls._dic
            return obj
    
    class Singleton(Base):
        pass
    
    s1 = Singleton()
    s1.name = "single"
    s2 = Singleton()
    
    print(s1,s1.__dict__)
    print(s2,s2.__dict__)
    
    '''
    <__main__.Singleton object at 0x000001C462BD1550> {'name': 'single'}
    <__main__.Singleton object at 0x000001C462BCAF60> {'name': 'single'}
    '''
    
  • 相关阅读:
    线程和进程
    Java多线程实现(四种方法)
    Java中的锁
    synchronized和java.util.concurrent.locks.Lock
    Lock的实现类ReentrantLock&Condition类的await/signal/signalAll(生产者消费者场景)
    synchronized&Object类的wait/notify/notifyAll(生产者消费者场景)
    SQL语句优化
    面试
    数据库三大范式
    设计模式之JDK动态代理源码分析
  • 原文地址:https://www.cnblogs.com/bowendown/p/12593734.html
Copyright © 2020-2023  润新知