一、单例模式理论
单例模式:
保证某一个类只有一个实例,而且在全局只有一个访问点
优点:
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