单例模式(python)

什么是单例模式:
单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在。当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场。
比如,系统的配置信息,在整个项目种很多地方会使用到,但是配置信息是不会在项目种被更改的,如果重复的创建配置信息的对象的化,会严重的浪费内存资源,如果能只存在一个对象,那就好了,由此而生的单例模式。
单例模式的创建有以下几个方式:
1.做成一个模块。
例:
在一个a.py文件中写好配置文件的信息的类方法,并给它创建了一个实例对象。再项目中要使用的时候,就直接 from a import singleton 把这个实例对象导进来。

class Singleton(object):
    def test(self):
        pass
singleton = Singleton()

2.利用装饰器。
例:
利用了下闭包。 在创建test方法的时候,执行singleton(test)语句。
外层函数调用内层函数,内层函数使用外层函数中的test对象。用一个字典instances 来判断是否已经创建了实例,若没有则创建test的实例对象,并把test类 和 test实例对象存到字典中,返回test;若已经创建,则直接返回字典中存储的test实例对象。(这里在多线程中出现资源抢夺问题,可以加锁解决。)

def singleton(cls):
    instances = {}
    def singleton_in(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
    	return instances[cls]
	return singleton_in
	
@singleton    #这句话就大致可以理解 test()=singleton(test)
class test(object):
    pass
a=test()
b=test()

3.重写类的__new__方法。
例:
new :必须得有一个参数,表示要实例化的类,必须得有返回值,返回值是实例化出来的实例。类被实例化时,是先执行__new__方法,再执行__init__方法,__init__方法中的self是__new__方法中返回的实例对象。
代码中用__instance的类属性做控制,这个属性存储的是第一次实例化的对象。
里面有with Singleton.__lock ,上下文资源管理器来给判断语句加上锁。这样就可防止多线程中的资源抢夺的问题,造成创建了多个实例。

class Singleton(object):
    _lock = threading.Lock()

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._lock:
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = object.__new__(cls)  
        return Singleton._instance

4.利用元类机制(原理和上一种一样)
metaclass
metaclass=SingletonType这句话的意思是创建Test类用SingletonType方法来创建, 即执行SingletonType() 这个语句,调用__call__方法。
Test创建一个实例对象后,以后再创建时,只是让变量b指向实例对象的地址,也不会再执行__init__的方法,即b = Test()中 不传参数也可以执行。

import threading

class SingletonType(type):
    _lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls._instance

class Test(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name
    def single(self,aaa):
        print('唱歌',aaa)

    def happy(self):
        print('唱歌')    

a = Test('1111')
b = Test()
a.single('山无棱')
b.single('天地合')
print(id(a))
print(id(b))

猜你喜欢

转载自blog.csdn.net/weixin_43778491/article/details/87524217