python设计模式之一-单例模式

引言

在面向对象的世界里,对象是对客观事物的抽象,类是对对象的抽象。它们之间的关系是,对象是类的实例,类是对象的模板。

这段文字表述起来费劲,理解起来也费劲,还是讲生活中的例子吧。比如说“大河”,一联想到这个词,不同的人脑海中的印象是不一样的,有的是“大漠孤烟直,长河落日圆”,有的是“春江潮水连海平,海上明月共潮生”,有的是“星垂平野阔,月涌大江流”。在这个例子中,大河可以认为是一个类,大河具有所有河流的共性特征,如有河堤,有长度,会流向大海等特性,而几句诗中的“石羊河”、“浏阳河”、“长江”等分别是大河的一个实例化对象。

在大河的例子中,一个大河类可以有多个不同的实例。可是,我们今天的主角-单例模式,应用单例模式的类却只能有一个实例。

比如我们常见的操作系统的任务管理器,它就是一个单例模式的实现。

定义

单例模式(singleton pattern):确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 这个定义有三个要点

  1. 某个类只能有一个实例
  2. 类应当自行创建这个实例
  3. 它必须向整个系统提供这个实例

UML结构

singleton uml 角色:单例本身

优缺点

优点
  1. 应用单例模式实例化类在应用程序域中只存在一个对象,满足业务需要的同时,无疑也能降低内存消耗,提高计算机性能。
  2. 由于实例化的过程由类本身完成,可方便地选择实例时机。
缺点
  1. 由于单例模式通常为单一类且不允许继承,所以它的扩展能力受限。
  2. 由于上一点的原因,单例类通常承载了过多的职能,违反了单一职责原则。

实例

Lilei和Hanmeimei经过多年的爱情长跑,终于迈入婚姻的殿堂。婚后不久,就有了爱情的结晶,小朋友名叫LittleMango。

In [6]:
class SingletonBase(type):
    def __init__(self,*args,**kwargs):
        self._instance=None
        super().__init__(*args,**kwargs)
    def __call__(self,*args,**kwargs):
        if self._instance is None:
            self._instance=super(SingletonBase,self).__call__(*args,**kwargs)
        return self._instance
    
class LittleMango(metaclass=SingletonBase):
    def show_my_age(self):
        print('I\'m 5 years old')
        
if __name__ == "__main__":
    s1=LittleMango()
    s2=LittleMango()
    print('s1:',id(s1))
    print('s2:',id(s2))
    
s1: 800311678008
s2: 800311678008

通过上面的实例,我们看见s1和s2引用了同一个内存地址,这样,我们就实现了单例模式。在项目应用中,如果把SingletonBase封装起来,需要实现单例模式的地方继承此类即可。