有這么一種場景,Web服務中有一個全局資源池,在需要使用的地方就自然而言引用該全局資源池即可,此時可以將該資源池以單例模式實現。隨后,需要為某一特殊業務場景專門準備一個全局資源池,于是額外復制一份代碼新建了一個全局資源池,這里的問題是本身兩個池子沒有任何區別,僅僅為了隔離資源而需要兩個單例,這里存在一個代碼復用問題。
Python 使用單例模式最佳方案是使用元類
class Singleton(type):"""單例模式的元類"""_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super().__call__(*args, **kwargs)return cls._instances[cls]
為解決上述問題,Python 中推薦以如下方式實現:
class Singleton(type):"""單例模式的元類"""_instances = {}def __call__(cls, *args, **kwargs):if cls not in cls._instances:cls._instances[cls] = super().__call__(*args, **kwargs)return cls._instances[cls]class SingletonBean(metaclass=Singleton):"""單例Bean父類"""passclass ConnectionPool:"""公共代碼"""def __init__(self, min_size, max_size, params):print(min_size, max_size, params)class ConnectionPool4A(SingletonBean, ConnectionPool):def __init__(self):super().__init__(min_size=10,max_size=100,params={...: ...})class ConnectionPool4B(SingletonBean, ConnectionPool):def __init__(self):super().__init__(min_size=30,max_size=30,params={...: ...})o1 = ConnectionPool4A()
print(id(o1))
o2 = ConnectionPool4B()
print(id(o2))
o3 = ConnectionPool4A()
print(id(o3))
o4 = ConnectionPool4B()
print(id(o4))
但是由于元類沖突,可能不一定可以:
class MyMeta1(type):...class MyMeta2(type):...class A1(metaclass=MyMeta1):...class A2(metaclass=MyMeta2):...class B(A2, A1):...print(type(B))