Singleton:
1, to ensure that only one object class has been created and
2, provides a global access point to the object
parallel access 3, control of the shared resource
Achieve a singleton easiest way:
the privatization of the constructor, and create a static method to complete object initialization
Be used:
a class object is required only one instance
Example disadvantage single mode
1, the global variables may be erroneously modified
2, creating multiple references to the same object
3, all depend on the class of global variables are due to changes in a closely coupled as a class of global data, which may unintentionally the impact of another class
A classic singleton
Only generates a class instance Singleton
# -*- coding: utf-8 -*-
class Singleton(object):
def __new__(cls):
if not hasattr(cls, "_instance"):
cls._instance = super(Singleton, cls).__new__(cls)
return cls._instance
if __name__ == '__main__':
s1 = Singleton()
s2 = Singleton()
print(s1)
print(s2)
print(s1 == s2)
print(s1 is s2)
"""
<__main__.Singleton object at 0x1021d58d0>
<__main__.Singleton object at 0x1021d58d0>
True
True
"""
Second, lazy instantiation
The actual object creation occurs in get_instance ()
# -*- coding: utf-8 -*-
class Singleton(object):
__instance = None
def __init__(self):
if not Singleton.__instance:
print("create...")
else:
print("already exist...")
@classmethod
def get_instance(cls):
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
if __name__ == '__main__':
s1 = Singleton.get_instance() # 实例化
s2 = Singleton.get_instance() # 已存在,不会实例化
print(s1)
print(s2)
print(s1 == s2)
print(s1 is s2)
"""
create...
<__main__.Singleton object at 0x101ad5860>
<__main__.Singleton object at 0x101ad5860>
True
True
"""
Third, the single-state mode Monostate
All objects share the same state
# -*- coding: utf-8 -*-
class Borg(object):
__data = {"age": 23}
def __init__(self):
self.__dict__ = self.__data
if __name__ == '__main__':
b1 = Borg()
b2 = Borg()
# b1 和 b2是不同的对象,共享了相同的属性
print(b1)
print(b2)
# 修改b1对象, b2对象的属性也变化了
b1.name = "Tom"
print(b1.__dict__)
print(b2.__dict__)
"""
<__main__.Borg object at 0x102345f60>
<__main__.Borg object at 0x1023452e8>
{'age': 23, 'name': 'Tom'}
{'age': 23, 'name': 'Tom'}
"""
Fourth, based on single embodiment metaclass
Metaclass control class instantiation
# -*- coding: utf-8 -*-
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
if __name__ == '__main__':
logger1 = Logger()
logger2 = Logger()
print(logger1)
print(logger2)
"""
<__main__.Logger object at 0x1013658d0>
<__main__.Logger object at 0x1013658d0>
"""
Fifth, a single-mode application Example
The database synchronization
# -*- coding: utf-8 -*-
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]
import sqlite3
class Database(metaclass=MetaSingleton):
connection = None
def __init__(self, db_url):
self.db_url = db_url
def get_cursor(self):
if self.connection is None:
self.connection = sqlite3.connect(self.db_url)
self.cursor = self.connection.cursor()
return self.cursor
if __name__ == '__main__':
db_url = "db.sqlite3"
cursor1 = Database(db_url).get_cursor()
cursor2 = Database(db_url).get_cursor()
print(cursor1)
print(cursor2)
"""
<sqlite3.Cursor object at 0x101b4c490>
<sqlite3.Cursor object at 0x101b4c490>
"""
Six, two single-mode application Example
Monitoring server, shared server data
# -*- coding: utf-8 -*-
class HealthCheck(object):
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs)
return cls._instance
def __init__(self):
self.servers = []
def add_server(self, server):
self.servers.append(server)
def pop_server(self):
return self.servers.pop()
def show_server(self):
print("*" * 10)
for server in self.servers:
print(server)
print("*" * 10)
if __name__ == '__main__':
h1 = HealthCheck()
h2 = HealthCheck()
h1.add_server("server1")
h1.add_server("server2")
h1.add_server("server3")
h2.pop_server()
h2.show_server()
"""
**********
server1
server2
**********
"""
to sum up
1, when a class requires only one object, you can use a single embodiment mode
2, classic single embodiment mode, allowing multiple instantiated, but returns the same object
3, Borg-state mode or single Monostate share the same state allows the creation of multiple objects
4, singleton service may be applied between multiple, consistent database operation
Reference:
"Design Mode Python 2nd edition" Chapter singleton design pattern