一、单例模式理论

单例模式:
   保证某一个类只有一个实例,而且在全局只有一个访问点
优点:
   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  in  range ( 3 ):
         print ( "Entity {} begin to run..." . format (i))
         =  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()