前言
单例模式可能是最简单的设计模式,单例是非常通用的对象。让你能够保证一个类只有一个实例, 并提供一个访问该实例的全局节点。
我们可以将船的船长视为单例模式的现实生活中的例子。在船上,他是负责人。他负责重要的决定,由于这一责任,他收到了一些请求。
如前所述,单例模式的一个用例是创建一个维护程序全局状态的单个对象。其他可能的用例如下:
class Singleton:
"""Definition of a Singleton object."""
singleton_instance = None
def __init__(self):
"""
Override the initialization
mechanism, returning only the single instance.
"""
...
@staticmethod
def get_singleton():
"""
Method for fetching the Singleton instance.
Is static so that it can be accessed everywhere.
"""
...
@staticmethod
def update_singleton(val):
"""
Method for setting value of Singleton instance.
Is static so that it can be accessed everywhere.
"""
...
复制代码
存储在 Singleton 实例中的数据是任意的。重要的是,无论数据,呼叫者和范围如何,Singleton 对象都会返回同一实例。这使得单元在实现诸如全局设置或运行配置之类的内容时有用。
单例例子
使用下面的代码片段来播放 Active Singleton 实现。尝试用数据结构(例如字典)替换可变 Singleton_instance,并查看 Getter 和 Setter 的实现如何更改。尝试编写一些共享 Singleton 实例的功能。
class Singleton:
"""Definition of a Singleton object."""
# Maintain state of Singleton
singleton_instance = None
def __init__(self):
"""Override the initialization mechanism."""
if Singleton.singleton_instance is None:
Singleton.singleton_instance = self
@staticmethod
def get_singleton():
"""
Method for fetching the Singleton instance.
Is static so that it can be accessed everywhere.
"""
if Singleton.singleton_instance is None:
Singleton() # Call __init__ to initialize instance
return Singleton.singleton_instance
@staticmethod
def update_singleton(val):
"""
Method for setting value of Singleton instance.
Is static so that it can be accessed everywhere.
"""
if Singleton.singleton_instance is None:
Singleton() # Call __init__ to initialize instance
Singleton.singleton_instance = val
Singleton.update_singleton("Michael")
print("Value in Singleton instance is: " + Singleton.get_singleton())
Singleton() # Try to create a new Singleton instance
print("Value in Singleton instance is STILL: " + Singleton.get_singleton())
复制代码
单例模式也可以通过使单例类使用元类(其类型,具有先前定义的元类)来实现。根据需要,元类的 __call__()
方法保存的代码可确保只能创建类的一个实例:
class SingletonMeta(type):
"""
The Singleton class can be implemented in different ways in Python. Some
possible methods include: base class, decorator, metaclass. We will use the
metaclass because it is best suited for this purpose.
"""
_instances = {}
def __call__(cls, *args, **kwargs):
"""
Possible changes to the value of the `__init__` argument do not affect
the returned instance.
"""
if cls not in cls._instances:
instance = super().__call__(*args, **kwargs)
cls._instances[cls] = instance
return cls._instances[cls]
class Singleton(metaclass=SingletonMeta):
def some_business_logic(self):
"""
Finally, any singleton should define some business logic, which can be
executed on its instance.
"""
# ...
if __name__ == "__main__":
# The client code.
s1 = Singleton()
s2 = Singleton()
if id(s1) == id(s2):
print("Singleton works, both variables contain the same instance.")
else:
print("Singleton failed, variables contain different instances.")
复制代码
单例模式优缺点
优点:
你可以保证一个类只有一个实例。
你获得了一个指向该实例的全局访问节点。
仅在首次请求单例对象时对其进行初始化。
缺点:
违反了单一职责原则。 该模式同时解决了两个问题。
单例模式可能掩盖不良设计, 比如程序各组件之间相互了解过多等。
该模式在多线程环境下需要进行特殊处理, 避免多个线程多次创建单例对象。
单例的客户端代码单元测试可能会比较困难, 因为许多测试框架以基于继承的方式创建模拟对象。 由于单例类的构造函数是私有的, 而且绝大部分语言无法重写静态方法, 所以你需要想出仔细考虑模拟单例的方法。 要么干脆不编写测试代码, 或者不使用单例模式。
参考链接:
评论