单例方法 – Python设计模式
先决条件:单例设计模式 |介绍
单例方法是一种创建设计模式,是我们可用的最简单的设计模式之一。这是一种提供一个且仅一个特定类型的对象的方法。它只涉及一个类来创建方法和指定对象。
单例设计模式可以通过一个非常简单的数据库连接示例来理解。当每个对象创建到数据库的唯一数据库连接时,它将极大地影响项目的成本和费用。所以,建立一个单一的连接总是比建立额外的不相关的连接更好,这可以通过Singleton Design Pattern轻松完成。
Definition: The singleton pattern is a design pattern that restricts the instantiation of a class to one object.
现在让我们看一下单例设计模式的不同实现。
方法1:Monostate/Borg Singleton 设计模式
单例行为可以通过 Borg 的模式来实现,但不是只有一个类的实例,而是有多个实例共享相同的状态。这里我们不关注实例身份的共享,而是关注共享状态。
Python3
# Singleton Borg pattern
class Borg:
# state shared by each instance
__shared_state = dict()
# constructor method
def __init__(self):
self.__dict__ = self.__shared_state
self.state = 'GeeksforGeeks'
def __str__(self):
return self.state
# main method
if __name__ == "__main__":
person1 = Borg() # object of class Borg
person2 = Borg() # object of class Borg
person3 = Borg() # object of class Borg
person1.state = 'DataStructures' # person1 changed the state
person2.state = 'Algorithms' # person2 changed the state
print(person1) # output --> Algorithms
print(person2) # output --> Algorithms
person3.state = 'Geeks' # person3 changed the
# the shared state
print(person1) # output --> Geeks
print(person2) # output --> Geeks
print(person3) # output --> Geeks
Python3
# Double Checked Locking singleton pattern
import threading
class SingletonDoubleChecked(object):
# resources shared by each and every
# instance
__singleton_lock = threading.Lock()
__singleton_instance = None
# define the classmethod
@classmethod
def instance(cls):
# check for the singleton instance
if not cls.__singleton_instance:
with cls.__singleton_lock:
if not cls.__singleton_instance:
cls.__singleton_instance = cls()
# return the singleton instance
return cls.__singleton_instance
# main method
if __name__ == '__main__':
# create class X
class X(SingletonDoubleChecked):
pass
# create class Y
class Y(SingletonDoubleChecked):
pass
A1, A2 = X.instance(), X.instance()
B1, B2 = Y.instance(), Y.instance()
assert A1 is not B1
assert A1 is A2
assert B1 is B2
print('A1 : ', A1)
print('A2 : ', A2)
print('B1 : ', B1)
print('B2 : ', B2)
Python3
# classic implementation of Singleton Design pattern
class Singleton:
__shared_instance = 'GeeksforGeeks'
@staticmethod
def getInstance():
"""Static Access Method"""
if Singleton.__shared_instance == 'GeeksforGeeks':
Singleton()
return Singleton.__shared_instance
def __init__(self):
"""virtual private constructor"""
if Singleton.__shared_instance != 'GeeksforGeeks':
raise Exception ("This class is a singleton class !")
else:
Singleton.__shared_instance = self
# main method
if __name__ == "__main__":
# create object of Singleton Class
obj = Singleton()
print(obj)
# pick the instance of the class
obj = Singleton.getInstance()
print(obj)
输出:
Algorithms
Algorithms
Geeks
Geeks
Geeks
双重检查锁定单例设计模式
很容易注意到,一旦创建了一个对象,线程的同步就不再有用了,因为现在 object 永远不会等于 None 并且任何操作序列都会导致一致的结果。
因此,当对象等于 None 时,只有我们会在 getInstance 方法上获取Lock 。
Python3
# Double Checked Locking singleton pattern
import threading
class SingletonDoubleChecked(object):
# resources shared by each and every
# instance
__singleton_lock = threading.Lock()
__singleton_instance = None
# define the classmethod
@classmethod
def instance(cls):
# check for the singleton instance
if not cls.__singleton_instance:
with cls.__singleton_lock:
if not cls.__singleton_instance:
cls.__singleton_instance = cls()
# return the singleton instance
return cls.__singleton_instance
# main method
if __name__ == '__main__':
# create class X
class X(SingletonDoubleChecked):
pass
# create class Y
class Y(SingletonDoubleChecked):
pass
A1, A2 = X.instance(), X.instance()
B1, B2 = Y.instance(), Y.instance()
assert A1 is not B1
assert A1 is A2
assert B1 is B2
print('A1 : ', A1)
print('A2 : ', A2)
print('B1 : ', B1)
print('B2 : ', B2)
输出:
A1 : __main__.X object at 0x02EA2590
A2 : __main__.X object at 0x02EA2590
B1 : __main__.Y object at 0x02EA25B0
B2 : __main__.Y object at 0x02EA25B0
单例设计模式的经典实现
在单例设计模式的经典实现中,我们简单地使用静态方法来创建能够返回共享资源的 getInstance 方法。我们还使用所谓的Virtual private Constructor来引发异常,尽管这并不是必需的。
Python3
# classic implementation of Singleton Design pattern
class Singleton:
__shared_instance = 'GeeksforGeeks'
@staticmethod
def getInstance():
"""Static Access Method"""
if Singleton.__shared_instance == 'GeeksforGeeks':
Singleton()
return Singleton.__shared_instance
def __init__(self):
"""virtual private constructor"""
if Singleton.__shared_instance != 'GeeksforGeeks':
raise Exception ("This class is a singleton class !")
else:
Singleton.__shared_instance = self
# main method
if __name__ == "__main__":
# create object of Singleton Class
obj = Singleton()
print(obj)
# pick the instance of the class
obj = Singleton.getInstance()
print(obj)
输出:
__main__.Singleton object at 0x014FFE90
__main__.Singleton object at 0x014FFE90
类图
单例设计模式类图
使用单例方法的优点:
- 初始化:由 Singleton 方法创建的对象只有在第一次被请求时才会被初始化。
- 访问对象:我们获得了对对象实例的全局访问权限。
- 实例计数:在单例方法中,类不能有多个实例
使用单例方法的缺点:
- 多线程环境:在多线程环境中使用单例方法并不容易,因为我们必须注意多线程不会多次创建单例对象。
- 单一职责原则:由于 Singleton 方法是一次解决两个问题,它不遵循单一职责原则。
- 单元测试过程:当他们将全局状态引入应用程序时,这使得单元测试非常困难。
适用性
- 全局变量控制:在特别需要对全局变量进行强控制的项目中,强烈推荐使用单例方法
- 日常开发人员使用:单例模式通常用于提供日志记录、缓存、线程池和配置设置,并且经常与工厂设计模式结合使用。
进一步阅读: Java中的单例方法,带有示例的单例设计模式实践