- List item
单例模式
保证类只有一个实例对象,并且提供全局访问点,控制共享资源的冰箱访问
实现单例模式的方法:
构造函数私有化,创建一个静态方法来完成对象的初始化。
class Singleton(object):
def __new__(cls):
if not hasattr(cls, 'instance'):
#cls.instance = super(Singleton,cls).__new__(cls)
# cls 参数代表着要实例化的类, new 方法必须要有返回值,返回实例化的对象
cls.instance = super().__new__(cls)
print("new")
return cls.instance
def __init__(self):
print("init")
# ps __init__ 和 new 方法的区别:
# new 是构造对象,分配内存空间,而 init 是对实例化出来的对象进行一些其他参数的初始化操作
s = Singleton()
s1 = Singleton()
print(s)
print(s1)
python]$ python3 singleton.py
new
init
new
init
<__main__.Singleton object at 0x7f7e5e6d9550>
<__main__.Singleton object at 0x7f7e5e6d9550>
单例模式的懒汉模式
## 单例的懒汉模式: 调用方法时才创建
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
s = Singleton()
print(s)
print("object created", Singleton.getInstance())
s1 = Singleton()
print(s1)
s2 = Singleton()
print(s2)
console
python3 singleton.py
__init__method called ...
<__main__.Singleton object at 0x7fb35bbbd438>
__init__method called ...
object created <__main__.Singleton object at 0x7fb35bbbfdd8>
Instance already created <__main__.Singleton object at 0x7fb35bbbfdd8>
<__main__.Singleton object at 0x7fb35bbbfe10>
Instance already created <__main__.Singleton object at 0x7fb35bbbfdd8>
<__main__.Singleton object at 0x7fb35bb494a8>
模块级别的单例模式
# singleton.py
class Singleton:
def __init__(self, name, id):
self.name = name
self.id = id
singleton = Singleton("nini",1)
# a.py
from singleton import singleton
print("import a")
print(singleton)
print(" a: name: {} id: {}".format(singleton.name, singleton.id))
#b.py
from singleton import singleton
import a
print(singleton)
print(" b name: {} id: {}".format(singleton.name, singleton.id))
python]$ python3 b.py
import singleton
import a
<singleton.Singleton object at 0x7f45d3c996d8>
a: name: nini id: 1
<singleton.Singleton object at 0x7f45d3c996d8>
b: name: nini id: 1
在执行 python 命令时, 同一个模块只被导入一次。如果已经导入,则返回该模块的对象,如果没有导入,则导入该模块,并实例化。当同一个模块再次被导入时,它不会再次初始化,因为单例模式只能有一个对象
Monostate 单态模式
class Borg:
__shared_state = {"1":"2"}
def __init__(self):
self.x =1
self.__dict__ = self.__shared_state
b = Borg()
b1 = Borg()
b.x = 4
print("Borg Object 'b':", b)
print("Borg Object 'b1':", b1)
print("Borg Object state 'b'", b.__dict__)
print("Borg Object state 'b1'", b1.__dict__)
python3 singleton.py
Borg Object 'b': <__main__.Borg object at 0x7fdbaba004a8>
Borg Object 'b1': <__main__.Borg object at 0x7fdbaba004e0>
Borg Object state 'b' {'1': '2', 'x': 4}
Borg Object state 'b1' {'1': '2', 'x': 4}
b 和 b1 是两个对象,但是共享一个 dict
另外一只实现方式:
class Borg(object):
__shared_state = {"1":"2"}
def __new__(cls, *args, **kwargs):
obj = super(Borg,cls).__new__(cls)
obj.__dict__ = cls.__shared_state
return obj
元类和单例模式
class Myint(type):
def __call__(cls, *args, **kwargs):
print("***** Here is my int ****",args)
print("Now do whatever you want with these objects...")
return type.__call__ (cls, *args, **kwargs)
class int(metaclass=Myint):
def __init__(self, x,y):
self.x =x
self.y =y
## 如果一个类实现了 __call__ 方法那么就可以像调用函数一样调用他
i = int(5,6)
# 元类控制着对象的实例化,元类对类创建和对象实例化有着更多的控制权,所以可以用元类实现单例模式
python3 singleton.py
***** Here is my int **** (5, 6)
Now do whatever you want with these objects...
使用元类实现单例模式:
class MetaSingle(type):
__instance = {}
def __call__(cls, *args, **kargs):
if cls not in cls.__instance:
cls.__instance[cls] = super(MetaSingle, cls).__call__(*args, **kargs)
return cls.__instance[cls]
class Logger(metaclass = MetaSingle):
pass
logger1 = Logger()
logger2 = Logger()
print(logger1, logger2)
python3 singleton.py
<__main__.Logger object at 0x7fd4dec5a4e0> <__main__.Logger object at 0x7fd4dec5a4e0>
单例模式的实际例子
# example: 为基础设置提供运行状况的监控服务,我们将 HealthCheck 类作为单例实现,我们还要维护一个被监控的服务器列表
class HealthyCheck:
__instance = None
def __new__(cls, *args, **kwargs):
if not HealthyCheck.__instance:
cls.__instance = super(HealthyCheck,cls).__new__(cls, *args, **kwargs)
print('create heathycheck instance')
return HealthyCheck.__instance
def __init__(self):
self._servers = []
print("init healthy check")
def addServer(self):
self._servers.append("server1")
self._servers.append("server2")
self._servers.append("server3")
self._servers.append("server4")
def changeServer(self):
self._servers.pop()
self._servers.append("server5")
hc1 = HealthyCheck()
hc2 = HealthyCheck()
print(hc1,hc2)
hc1.addServer()
print("Schedule health check for servers (1)...")
for i in range(4):
print("Checking", hc1._servers[i])
hc2.changeServer()
print("Schedule health check for servers (2)...")
for i in range(4):
print("Checking", hc2._servers[i])
单例模式的缺点
全局变量可能在某处被误改,而开发人员认为他没有改变,还在应用程序的其他地方使用他
由于单例模式只创建一个对象,在这种情况下会对同一个对象创建多个引用
依赖全局变量的类,会和其他类紧密耦合。可能在无意中改变其他的类