单例模式
什么是单例模式
意图:创建一个类,保证一个类只有一个实例,并提供一个访问它的全局访问点。单例相当于是全局变量,内部的方法可能会被更改
角色:
单例(Singleton)
适用场景
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时;
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
优点:
对唯一实例的受控访问
单例相当于全局变量,但防止了命名空间被污染
与单例模式功能相似的概念:全局变量、静态变量(方法)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, "_instance"): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance class MyClass(Singleton): def __init__(self, name): self.name = name a = MyClass("a") print(a) print(a.name) b = MyClass('b') # print(b) print(b.name) b.name = 'xxx' # print(a) print(a.name) 单例模式
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
单例模式: 单例模式 每次只实例化一个对象!造对象的过程是__new__方法,给对象传数据是__init__的方法,做成一个实例! 类不管怎样创建多个实例,对象都会以第一个实例为准 #方式一:文件导入,文件内创建一个对象,通过这个对象导入方法 #方式二:通过类方法实例化对象 class Foo: _instance = None def __init__(self): pass @staticmethod def get_instance(cls): if cls._instance: return cls._instance else: obj = cls() cls._instance = obj return obj #方式三: __new__ class Foo(object): _instance = None def __init__(self): pass def __new__(cls, *args, **kwargs): if cls._instance: return cls._instance else: obj = object.__new__(cls, *args, **kwargs) cls._instance = obj return obj 用途: - 自定义curb组件时,对于类构建的信息,仅需一个实例 - 发布文章,特殊字符的过滤: KindEditor 单例模式深究
# 单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在 # 场景:比如,某个服务器程序的配置信息存放在一个文件中,客户端通过一个 AppConfig 的类来读取配置文件的信息。 # 如果在程序运行期间,有很多地方都需要使用配置文件的内容,也就是说,很多地方都需要创建 AppConfig 对象的实例, # 这就导致系统中存在多个 AppConfig 的实例对象,而这样会严重浪费内存资源,尤其是在配置文件内容很多的情况下。 # 事实上,类似 AppConfig 这样的类,我们希望在程序运行期间只存在一个实例对象。
实现单例模式的4种方法
# 实现的方法: # # # (1)__new__ # (2)使用模块 # (3)使用装饰器 # (4)使用元类 # 第一种方法 # python的模块是天然的单例模式,第一次导入时,生成.pyc文件,第二次载入时,直接加载.pyc #mysingleton.py class Mysingleton(object): def foo(self): pass my_singleton = Mysingleton() # 在别的地方引入使用 # from mysingleton import my_singleton # my_singleton.foo() # 第二种方法,默认不存在,如果不存在就创建,如果存在就将创建的返回,不创建新的类 class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance = super(Singleton,cls).__new__(cls, *args, **kwargs) return cls._instance class MyClass(Singleton): a = 1 one = MyClass() two = MyClass() print(one == two) print("Singleton:",type(MyClass)) print("one:",type(one)) # True # Singleton: <class 'type'> # one: <class '__main__.MyClass'> # 第三种方法:使用装饰器只生成一个实例 from functools import wraps def singleton(f): instances = {} @wraps(f) def getinstance(*args,**kwargs): if f not in instances: instances['cls']=f(*args,**kwargs) return instances return getinstance @singleton class Myclass1(object): a=1 one = Myclass1() two = Myclass1() print(one == two) # 在上面,我们定义了一个装饰器 singleton,它返回了一个内部函数 getinstance, # 该函数会判断某个类是否在字典 instances 中,如果不存在,则会将 cls 作为 key, # cls(*args, **kw) 作为 value 存到 instances 中,否则,直接返回 instances[cls]。 # 第四种方法实现,元类 # 元类的作用:拦截类的创建,修改类的定义,返回修改过后的类 class Singleton(type): _instance = None def __call__(self, *args, **kwargs): if not self._instance: self._instance['cls']= super(Singleton, self).__call__(*args, **kwargs) return self._instance['cls'] # Python2 # class MyClass2(object): # __metaclass__ = Singleton # Python3 class MyClass2(metaclass=Singleton): pass
需要注意的类的内置方法__new__,__init__,__call__
# 1. # __new__(cls, *args, **kwargs) # 创建对象时调用,返回当前对象的一个实例; # 注意:这里的第一个参数是cls即class本身 # 2. # __init__(self, *args, **kwargs) # 创建完对象后调用,对当前对象的实例的一些初始化,无返回值, 即在调用__new__之后,根据返回的实例初始化; # 注意,这里的第一个参数是self即对象本身【注意和new的区别】 # 3. # __call__(self, *args, **kwargs) # 如果类实现了这个方法,相当于把这个类型的对象当作函数来使用,相当于 # 重载了括号运算符,使用对象() 即可调用
一般单例模式和线程安全的单例模式
#!/usr/bin/env python # -*- encoding: utf-8 -*- import time import threading class Singleton(object): def __init__(self): time.sleep(1) def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls) return cls._instance class Hello(Singleton): def __init__(self, name): self.name = name print(self.name) def Task(i): print(Hello(i)) class SingletonSafe(object): _instance_lock = threading.Lock() def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): with cls._instance_lock: if not hasattr(cls, '_instance'): cls._instance = super(SingletonSafe, cls).__new__(cls) return cls._instance class HelloSafe(SingletonSafe): def __init__(self, name): self.name = name print(self.name) def TaskSafe(i): print(HelloSafe(i)) if __name__ == '__main__': for i in range(10): t = threading.Thread(target=Task, args=(i,)) t.start() time.sleep(5) print('*'*100) for i in range(10): t = threading.Thread(target=TaskSafe, args=(i,)) t.start()