单例模式保证类有且只有一个实例,并提供一个访问他的全局访问点。 1.
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
cls.instance = super(Singleton, cls).__new__(cls)
return cls.instance
s = Singleton()
print("Object created", s)
s1 = Singleton()
print("Object created", s1)
2.
class Singleton:
__instance = None
def __init__(self):
if not Singleton.__instance:
print(" __init__ method called..")
else:
print("Instance already created:", self.getInstance())
@classmethod
def getInstance(cls):
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
3. 4.有时候我们并不关心生成的实例是否具有同一id,而只关心其状态和行为方式。我们可以允许许多个实例被创建,但所有的实例都共享状态和行为方式:
class Borg:
__shared_state = {"1":"2"}
def __init__(self):
self.x = 1
self.__dict__ = self.__shared_state
pass
b = Borg()
b1 = Borg()
b.x = 4
print("Borg Object 'b': ", b)
print("Borg Object 'b1': ", b1)
print("Object State 'b':", b.__dict__)
print("Object State 'b1':", b1.__dict__)
或者使用new方法:
In [16]: class Borg(object):
_shared_state = {}
def __new__(cls, *args, **kwargs):
obj = super(Borg, cls).__new__(cls, *args, **kwargs)
obj.__dict__ = cls._shared_state
return obj
4.元类实现
# 当我们调用Logger()初始化Logger时,将会调用类MetaSingleton中的__call__方法
In [1]: class MetaSingleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class Logger(metaclass=MetaSingleton):
pass
In [2]: l1 = Logger()
In [3]: l2 = Logger()
In [4]: id(l1)
Out[4]: 140568820684616
In [5]: id(l2)
Out[5]: 140568820684616
线程安全的写法:
In [9]: def synchronized(func):
...: func.__lock__ = threading.Lock()
...:
...: def synced_func(*args, **kws):
...: with func.__lock__:
...: return func(*args, **kws)
...:
...: return synced_func
...:
...:
In [10]: def Singleton(cls):
...: instances = {}
...:
...: @synchronized
...: def get_instance(*args, **kw):
...: if cls not in instances:
...: instances[cls] = cls(*args, **kw)
...: return instances[cls]
...:
...: return get_instance
...:
...:
In [11]: @Singleton
...: class test():
...: a = 1
...:
In [12]: s = test()
In [13]: s1 = test()
In [14]: id(s)
Out[14]: 140308601028336
In [15]: id(s1)
Out[15]: 140308601028336
实用场景: 1.数据库连接 2.应用健康检测 3.许多需要创建一个对象的场景,如线程池,缓存,对话框,等等。
优点: 通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。 缺点: 全局变量可能会在某一处被修改,一个同一对象存在多个引用,所有依赖于全局变量的类都会紧密耦合,因为一个类对全局数据的更改可能会无意中影响另一个类 Ref: 1.Learning Python Design Patterns 2.https://www.cnblogs.com/baiyb/p/8506438.html