1. 单例模式I
通过一个数据库应用程序来展示单例的应用。明显的是,跨不同服务的共享资源是数据库本身。
import sqlite3
class MetaSingleton(type):
_instance = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instance:
cls._instance[cls] = super(MetaSingleton, cls).__call__(*args, **kwargs)
return cls._instance[cls]
class Database(metaclass=MetaSingleton):
connection = None
def connect(self):
if self.connection is None:
self.connection = sqlite3.connect('db.sqlite3')
self.cursorobj = self.connection.cursor()
return self.cursorobj
db1 = Database().connect()
db2 = Database().connect()
print('Database Objects DB1', db1)
print('Database Objects DB2', db2)
- 以MetaSingleton为名创建一个元类
- Database类由MetaSingleton类装饰后,其行为表现为单例。因此,当数据库类被实例化时,它只创建一个对象
- 因为只有一个对象,所以对数据库的调用是同步的。此外,还能够节约系统资源
如果我们要开发的不是单个Web应用程序,而是集群化的情形,即多个Web应用程序共享单个数据库。单例就会变得不太方便,因为每增加一个应用程序,就要新建一个单例,添加一个对象来查询数据库。这导致数据库操作无法同步,并消耗大量资源。这种情况下,数据库连接池比实现单例好得多。
2. 单例模式II
全局维护一张可用服务器的列表,当添加或者删除服务器时,所有服务会使用修改后的服务器列表。
class HealthCheck:
_instance = None
def __new__(cls, *args, **kwargs):
if not HealthCheck._instance:
HealthCheck._instance = super(HealthCheck, cls).__new__(cls, *args, **kwargs)
return HealthCheck._instance
def __init__(self):
self._servers = []
def addServer(self):
self._servers.append('Server 1')
self._servers.append('Server 2')
self._servers.append('Server 3')
self._servers.append('Server 4')
def changeServer(self):
self._servers.pop()
self._servers.append('Server 5')
if __name__ == '__main__':
hc1 = HealthCheck()
hc2 = HealthCheck()
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])