“单例模式(Singleton Pattern)是一个比较简单的模式,其定义以下:
Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,并且自行实例化并向整个系统提供这个实例。)”
Excerpt From: 秦小波 著. “设计模式之禅(第 2 版)(华章原创精品).” iBooks.
能够经过plantuml查看html
@startuml class Singleton{ + name } note top:Singleton has a 'name' property.此处的Singleton表明下边代码中的File类 class Client note left: client get one singleton instance Client --> Singleton @enduml
因为此markdown不能展现故贴图java
import threading import time class Singleton(type): def __new__(cls, *args, **kwargs): return type.__new__(cls, *args, **kwargs) def __init__(self, *agrs, **kwargs): self.__instance = None super().__init__(*agrs, **kwargs) def __call__(self, *args, **kwargs): if self.__instance is None: # time.sleep(2) 模拟线程切换,此时不能保证多线程单例实现 self.__instance = super().__call__(*args, **kwargs) return self.__instance else: return self.__instance class File(metaclass=Singleton): def __init__(self, name): self.name = name def create_file_instance(name): f = File(name) print(f) # if __name__ == "__main__": # thread1 = threading.Thread(target=create_file_instance, args=('abc', )) # thread2 = threading.Thread(target=create_file_instance, args=('bcd', )) # thread1.start() # thread2.start() # 若是有sleep会出现此状况: #<__main__.File object at 0x1052d34a8> #<__main__.File object at 0x1052d3390> # 若是没有高几率不会出现不一致的状况,由于代码消耗的cpu时间很短,不足以形成线程切换 # -------------------多线程下单例实现---------------- # def synchronized(func): func.__lock__ = threading.Lock() def lock_func(*args, **kwargs): with func.__lock__: return func(*args, **kwargs) return lock_func class SingletonSync(type): def __init__(self, *agrs, **kwargs): self.__instance = None super().__init__(*agrs, **kwargs) @synchronized def __call__(self, *args, **kwargs): if self.__instance is None: time.sleep(2) self.__instance = super().__call__(*args, **kwargs) return self.__instance else: return self.__instance class FileSync(metaclass=SingletonSync): def __init__(self, name): self.name = name def create_file_instance_sync(name): f = FileSync(name) print(f) if __name__ == "__main__": thread1 = threading.Thread(target=create_file_instance_sync, args=('abc', )) thread2 = threading.Thread(target=create_file_instance_sync, args=('bcd', )) thread1.start() thread2.start() #<__main__.FileSync object at 0x10fbd43c8> #<__main__.FileSync object at 0x10fbd43c8>
参考代码:Python Cookbook - 9.13.2 章节
同步锁机制: https://blog.csdn.net/lucky40...
学习《设计模式之禅》这本书,但又没有使用 java 语言,便突发奇想,结合设计模式的书,参考 python 的相关书籍编写 python 的设计模式的例子。相对于 java 来讲单例应该是设计模式中最好理解和最好编写的代码了,可是对于 python 而言,小白的我,仍是学习了不少知识点。python
metaclass ( __metaclass__
)
metaclass 能够指定某个类的元类,何为元类?就是建立类的类。 - 存在乎义:拦截类的建立、修改类、返回修改以后的类。 - 回到咱们的单例模式,就是利用元类来实现的,Singleton 类就是 File 类的元类,能够理解为是 Singleton 建立了 File 类,(注意是类而不是类的实例)。具体就是调用了__new__
方法。设计模式
__metaclass__
是实现自定义元类的一种方式,很少解释,有兴趣的能够参考以下两边文章,说的比较好,并且有 metaclass 更好的应用场景介绍markdown
https://www.cnblogs.com/Simon... https://www.liaoxuefeng.com/wiki/1016959663602400/1017592449371072
__new__
方法:很是基础的知识点,newe 函数是执行 init 以前执行的函数,真正建立类的是 new 函数,new 函数会逐级查找__metaclass__
(元类方法),若是找到就执行,找不到就继续查找父类,若是都没有最终会调到 type,type 也是一个元类,并且是像 int、string 等的元类,就是 type 建立了 int、string__call__
方法:File()执行的时候被调度的函数。全部定义了 call 方法的类均可以被称为是可执行的,就是能够当成一个函数执行。说了这几个知识点,若是不太懂元类,或者 call 方法,可能仍是不太好理解这个单例的执行,一个简单地方式就是回去跑一下试试。
说一下代码执行流程(只介绍 File 建立的流程):多线程
在 File()执行以前,在 File 被定义传来的时候 Singleton 的 new 函数就被执行了,目的就是为了建立出这个 File 类,这也是为何会写上 new 函数的缘由,其实不写不会影响单例模式,而后 Singleton 的 init 被执行,目的是为了建立 instance 实例,实例名称也有讲究,双下划线表示隐私属性不会被复写。接着,当 File 函数被执行时会调用 call 方法。ide
sleep 函数是为了模拟线程间切换,若是不切换高几率是不会出现建立两个不一样的实例的状况。函数
说给本身听,当是给本身学习的一个动力吧!学习