一、理解单例设计模式
单例模式提供的机制:确保类有且只有一个特定类型的对象,并提供全局访问点。
特性:
1.确保类有且只有一个对象被创建
2.为对象提供一个访问点,以使程序可以全局访问该对象
3.控制共享资源的并行访问。
解决了什么问题:避免了同一资源产生相互冲突的请求。(用于日志记录,数据库操作,打印机后台处理程序)
示例:
# encoding: utf-8
# 使用单例模式创建类
class Singleton(object):
# 创建新类前,先调用__new__
def __new__(cls):
# hasattr :判断是否有instance属性,
# if 没有就创建,if 有就直接返回
if not hasattr(cls,"instance"):
cls.instance = super(Singleton,cls).__new__(cls)
# print(cls.instance)
return cls.instance
# 未使用单例模式创建类
class Singleton2(object):
pass
# 用单例模式创建两个类
s0 = Singleton()
print ("Object created", s0)
s1 = Singleton()
print ("Object created", s1)
# 用非单例模式创建两个类
s2 = Singleton2()
print ("Object created", s2)
s3 = Singleton2()
print ("Object created", s3)
输出:
('Object created', <__main__.Singleton object at 0x02598250>)
('Object created', <__main__.Singleton object at 0x02598250>)
('Object created', <__main__.Singleton2 object at 0x02598270>)
('Object created', <__main__.Singleton2 object at 0x02598290>)
二、单例设计模式中的懒汉式实例化
特性:保证了需要使用的时候才创建对象。(防止导入模块,但没有使用,造成的浪费)
示例:
# encoding: utf-8
class Singleton:
__instance = None
def __init__(self):
if not Singleton.__instance:
print ("__init__ method called..")
else:
print ("Instance already created:",self.getInstance())
@classmethod
def getInstance(cls):
if not cls.__instance:
cls.__instance = Singleton()
return cls.__instance
s = Singleton() # 初始化,但不创建
print("Object created", Singleton.getInstance())# 使用的时候创建
s1 = Singleton()
三、模块级别的单例模式
默认情况python所有的模块都是单例,python模块的工作方式:
1.检查一个模块是否已经导入
2.如果导入,返回该模块对象。如果没导入,导入模块,并实例化。
四、Monostate单例模式
单态单例模式:所有对象共享相同状态。(关心的是状态和行为,而不是同一性)
示例:
# encoding: utf-8
class Borg:
__shared_state = {"1":"2"}
def __init__(self):
self.x = 1
self.__dict__ = self.__shared_state
pass
b = Borg()
b1 = Borg()
b.x = 4
print ("Borg Object 'b': ",b) # b和b1不是同一个对象
print ("Borg Object 'b1': ",b1)
print ("Borg State 'b': ",b.__dict__) # b和b1共享状态
print ("Borg State 'b1': ",b1.__dict__)
五、单例和元类
元类概念:元类是类的类。(a = 5 ,type(a) 为 int ,type(int) 为 type)
元类示例:
# encoding: utf-8
class MyInt(type):
def __call__(cls, *args, **kwds):
print ("**** Here is My int ****",args)
print ("Now do whatever you want with these objecys...")
return type.__call__(cls, *args, **kwds)
class int(metaclass = MyInt):
def __init__(self, x, y):
self.x = x
self.y = y
i = int(4,5)
元类的单例实现:
# encoding: 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
logger1 = Logger()
logger2 = Logger()
print (logger1,logger2)
输出:
<__main__.Logger object at 0x005AB070> <__main__.Logger object at 0x005AB070>
六、单例模式I
场景:多个web应用共享一个数据库,为了避免数据库操作冲突,采用单例模式
# encoding: utf-8
import sqlite3
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 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 ("Datebase Objects DB1", db1)
print ("Datebase Objects DB2", db2)
七、单例模式II
场景:运行状况监控服务。我们对监控对象的操作肯定是同一个,所以用单例模式实现。
# encoding: utf-8
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")
hc1 = HealthCheck()
hc2 = HealthCheck()
hc1.addServer()
print ("Schedule health check for server (1)..")
for i in range(4):
print ("Checking ",hc1._servers[i])
hc2.changeServer()
print ("Schedule health check for server (2)..")
for i in range(4):
print ("Checking ",hc2._servers[i])
八、单例模式的优缺点
1.优点:
1.1 减少资源的过度使用如在:线程池、缓存、对话框、注册表等
2.缺点:
2.1全局变量可能在某处已经被误改。
2.2同一个对象可能创建多个引用。
2.3依赖于全局变量的类都会耦合成全局数据,耦合度增加。
注:例子在python3中运行
本系列项目代码地址:Python-design-pattern