单例,顾名思义是一个实例,即在一个项目之中,单例的类只实例化一次。它常常应用于数据库操作、日志函数。
在一个大型项目中使用到日志和数据库操作的地方很多,不能每个文件都去单独实例化一次,此时单例模式就显示出了他的价值。
单例的核心在类的内部方法
__new__()
,每次实例化都是通过执行new函数来返回实例对象。单例就是在类里面定义一个作用域最高的标志性的属性,如果实例化过一次,那这个属性为True,否则为False,那么返回上次实例化的对象。
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。
当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): org = super(Singleton, cls) # 让cls继承指定的父类 Singleton cls._instance = org.__new__(cls) # 创建实例 return cls._instance # 返回具体的实例 # 复写内部方法__new__() # 通过hasattr函数判断该类实例化时有没有_instance属性 # 如果不存在,那么继承并返回原始的__new__方法给_instance属性 # 如果存在则直接返回_instance属性所指的对象
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): org = super(Singleton, cls) cls._instance = org.__new__(cls) return cls._instance class MyClass(Singleton): def __init__(self, name): self.name = name if __name__ == "__main__": a = MyClass("A") print(a.name) b = MyClass("B") print(a.name) print(b.name) b.name = 'C' print(a.name) print(b.name) 输出结果: A B B C C
单例模式的优点: 1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间; 2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用; 3、单例可长驻内存,减少系统开销。 单例模式的应用举例: 1、生成全局惟一的序列号; 2、访问全局复用的惟一资源,如磁盘、总线等; 3、单个对象占用的资源过多,如数据库等; 4、系统全局统一管理,如Windows下的Task Manager; 5、网站计数器。
1、单例模式的扩展是比较困难的; 2、赋于了单例以太多的职责,某种程度上违反单一职责原则(六大原则后面会讲到); 3、单例模式是并发协作软件模块中需要最先完成的,因而其不利于测试; 4、单例模式在某种情况下会导致“资源瓶颈”。