一、单例模式理论
单例模式:
保证某一个类只有一个实例,而且在全局只有一个访问点
优点:
1、由于单例模式要求在全局内只有一个实例,因而可以节省比较多的内存空间
2、全局只有一个接入点,可以更好地进行数据同步控制,避免多重占用
3、单例可长驻内存,减少系统开销
缺点:
1、单例模式的扩展是比较困难的
2、赋予了单例模式太多的职责,某种程度上违反了单一职责原则(六大设计原则之一)
3、单例模式是并发协作软件模块中需要最先完成的,因而其不利于测试
4、单例模式在某种情况下会导致资源瓶颈
应用场景:
1、生成全局唯一的变量,比如序列号
2、访问全局复用的唯一资源,如磁盘,总线等
3、单个对象占用的资源太多,如数据库等
4、系统全局统一管理,如windows下的任务管理器
二、对__new__的分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | # class Demo: # def __init__(self, name): # self.name = name # # def show_name(self): # print("Name is: {}".format(self.name)) # # if __name__ == '__main__': # # d = Demo("toby") # d.show_name() ''' 引用大神的描述: 这样便是__init__最普通的用法了。但__init__其实不是实例化一个类的时候第一个被调用的方法。 当使用Demo("toby")这样的表达式来实例化一个类时,最先被调用的方法其实是 __new__ 方法。 __new__ 方法是什么? __new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而__new__方法正是创建这个类实例的方法。 ''' class Demo: def __new__( cls , name): print ( "Call __new__" ) class_instance = super (Demo, cls ).__new__( cls ) print ( "new创建了类实例:" , class_instance) #打印一下 return class_instance #返回Demon类的一个实例给__init__,然后利用这个实例来调用类的__init__方法 def __init__( self , name): #那__init__用什么来接收__new__返回来的类实例呢?答案就是self print ( "init接收到new返回回来的类实例:" , self ) #打印一下这个self,也就是看一下由__new__产生的实例 print ( "Call __init__" ) self .name = name def show_name( self ): print ( "Name is: {}" . format ( self .name)) # # if __name__ == '__main__': # d = Demo("toby") # d.show_name() ''' 引用大神的总结: 所以,__init__ 和 __new__ 最主要的区别在于: 1、__init__ 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。 2、__new__ 通常用于控制生成一个新实例的过程。它是类级别的方法。 但是说了这么多,__new__最通常的用法是什么呢,我们什么时候需要__new__?,单例模式就是一个很好的例子 ''' |
三、单例模式(案例1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #coding:utf-8 import threading import time #这里使用方法__new__来实现单例模式 class Singleton( object ): #抽象单例 def __new__( cls , * args, * * kwargs): if not hasattr ( cls , "_instance" ): orig = super (Singleton, cls ) cls ._instance = orig.__new__( cls , * args, * * kwargs) return cls ._instance #总线 class Bus(Singleton): lock = threading.RLock() def sendData( self , data): self .lock.acquire() time.sleep( 3 ) print ( "Sending Signal Data..." , data) self .lock.release() #线程对象,为更加说明单例的含义,这里讲Bus对象实例化在了run里 class VisitEntity(threading.Thread): my_bus = "" name = "" def getName( self ): return self .name def setName( self , name): self .name = name def run( self ): self .my_bus = Bus() self .my_bus.sendData( self .name) if __name__ = = '__main__' : for i in range ( 3 ): print ( "Entity {} begin to run..." . format (i)) v = VisitEntity() v.setName( "Toby" + str (i)) v.start() |
四、单例模式(案例2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | #使用__new__类方法来保证只有一个实例被创建出来 class OneOnly( object ): _singleton = None def __new__( cls , * args, * * kwargs): if not cls ._singleton: #判断是否创建有实例,如果没有则调用super()函数来创建它 cls ._singleton = super (OneOnly, cls ).__new__( cls ) #构造方法__new__被调用时,会构造该类的一个新实例 return cls ._singleton #定义一个普通的类,仅有初始化方法__init__ class Test: def __init__( self , name): self .name = name #定义一个Demo类,并继承实现单例模式的OneOnly类 class Demo(OneOnly): def __init__( self , name): self .name = name def chage_name( self , new_name): self .name = new_name def show_name( self ): print ( "Name is: {}" . format ( self .name)) if __name__ = = '__main__' : #当通过OneOnly类中的构造方法构造实例时,总是会的得到完全相同的实例,内存地址也相同 # o1 = OneOnly() # o2 = OneOnly() # print(o1) # print(o2) #通过Test类创建出来的两个实例t1和t2,是两个不同的实例,内存地址也是不同的 # t1 = Test("toby") # t2 = Test("ttr") # print(t1) # print(t2) #Demo类继承了实现了单例模式的OneOnly类,因此,通过Demo类实例化出来的对象都是同一个对象 d1 = Demo( "toby" ) d2 = Demo( "ttr" ) d3 = Demo( "laowang" ) # 通过打印可知,他们的内存地址都是一样的 # print(d1) # print(d2) #发现打印出来的name都是"laowang",似乎最后创建的一个实例把前两个的给覆盖了 d1.show_name() d2.show_name() d3.show_name() #通过实例d1修改名字后,再通过实例d3和d2来查看,果然也一起改变了。由此证明他们确实是同一个实例 d1.chage_name( "juck" ) d3.show_name() d2.show_name() |
本文转自 TtrToby 51CTO博客,原文链接:http://blog.51cto.com/freshair/2069887