您的位置:首页 > 编程语言 > Python开发

python Singleton 模式

2013-06-06 16:27 302 查看
Singleton 模式,中文既为 单实例模式 。

一、代码示例

看一下普通的类:

class Normal(object):
_instance = []

config = ''

def set(self,value):
self.config = value

def get(self):
return self.confg

if __name__ == '__main__':
s1 = Normal()
s1.set('s1')

s2 = Normal()
s2.set('s2')

print id(s1)
print id(s2)
print s1.get()
print s2.get()
运行结果 :

ubuntu@yee:/tmp$ python t.py
139782948272976
139782948273040
s1
s2

可以看到,代码中生成了两个实例,每个实例都拥有自己的内存空间。

接下来看单实例的代码示例:

class Singleton(object):
_instance = []

config = ''

def __new__(cls,*args,**kwargs):
if not cls._instance:
cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
return cls._instance

def set(self,value):
self.config = value

def get(self):
return self.config

if __name__ == '__main__':
s1 = Singleton()
s1.set('config:s1')

s2 = Singleton()
s2.set('config:s2')

print id(s1)
print id(s2)
print s1.get()
print s2.get()

ubuntu@yee:/tmp$ python t.py
<__main__.Singleton object at 0x7f948b034c10>
<__main__.Singleton object at 0x7f948b034c10>
140275964136464
140275964136464
config:s2
config:s2
看到s2和s1 是同一个实例,所使用的都是同一个内存空间,所以 s1.set() 和s2.set()是设置了同一个变量 。

但是以上的代码也会有一个问题:线程安全

如果并发运行了两个线程,都检测到当前的 cls._instance = null ,那么都会创建新的线程,此时就全乱了。所以,我们需要加锁

#!/usr/bin/python
#-*- coding:utf8  -*-

import threading
import time
class Singleton(object):
_instance = []
config = ''

def __new__(cls,*args,**kwargs):
if not cls._instance:
print  "I will lock thread"
mlock = threading.Lock()
mlock.acquire()
cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
mlock.release()

return cls._instance

def set(self,value):
self.config = value

def get(self):
return self.config

def execute():
s1 = Singleton()
print str(id(s1)) + "\n"

if __name__ == '__main__':
thread1  =  threading.Thread(target=execute)
thread2  =  threading.Thread(target=execute)
thread1.start()
thread2.start()
只有第一次创建实例的时候才会加锁,所以不用担心会影响性能 。

搞清楚了上面的代码之后,就可以总结出单实例的优点了:

节省内存空间

二、单实例的使用场景 :

比方说,

OS在开机之后,会维护一份用户的配置文件,这份文件 从开机到关机期间只需要有一份,并且常驻内存之中。这个时间就需要使用单实例。

单实例可以使系统不必在用户去修改某一项配置的时候重新new一个实例,单实例对象是全局的,常驻内存的,所以只需要直接赋值就可以了。

三、为什么需要避免使用单实例

请自行google : why singleton bad

(使用百度的程序猿不是好程序猿)

http://www.cnblogs.com/vwxyzh/archive/2010/07/17/1779620.html

http://www.btsmth.com/show_topic.php?en_name=SoftEng&gid=81604
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: