先描述在python中的一个场景,我有个自定义的类,实例了一些transfer信息传递及线程池的作用,然后还需要被用来共享一些服务配置。 这时候稍不注意会出现一批新的类实例被创建。 这样造成了数据不能共享,浪费资源。 我知道大家也不想这样,但往往不注意就这样了。 肿么办? 可以直接上单例模式!
该文章写的有些乱,欢迎来喷 ! 另外文章后续不断更新中,请到原文地址查看更新。http://xiaorui.cc/?p=3165
那么什么是单例模式?
简单说单例模式可以保证一个类仅有一个实例, 并提供一个访问它的全局访问点——《设计模式》, 再废话一句,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。
– 特点
– 单例类只能有一个实例或给定数目的单例
– 单例类必须给所有其他对象提供这个实例
– 优点
– 避免对资源的多重占用,避免对同一个资源文件的同时操作,造成文件状态不一致
– 减少内存开支,尤其是需要频繁创建和使用的类
– 设置全局访问点,优化和共享资源访问
– 场景
– 减少在协同开发中产生类似的实例对象,节省资源
– 整个项目中需要一个共享访问带点或共享数据
.
这里不相信讲解代码了,实现很是简单,借用类变量做个标记,首先使用__new__创建实例对象。 如果你再次创建一个实例对象的时候,首先会在cls.instance判断是否已经创建过实例对象.这样就能防止实例被多次创建。 多线程的环境实现起来也简单,加了一个threading lock同步锁而已。
#xiaorui.cc import threading try: from synchronize import make_synchronized except ImportError: def make_synchronized(func): import threading func.__lock__ = threading.Lock() def synced_func(*args, **kws): with func.__lock__: return func(*args, **kws) return synced_func class Singleton(object): instance = None @make_synchronized def __new__(cls, *args, **kwargs): if cls.instance is None: cls.instance = object.__new__(cls, *args, **kwargs) return cls.instance def __init__(self): self.blog = "xiaorui.cc" def go(self): pass def worker(): e = Singleton() print id(e) e.go() def test(): e1 = Singleton() e2 = Singleton() e1.blog = 123 print e1.blog # 123 print e2.blog # 123 print id(e1) print id(e2) if __name__ == "__main__": test() task = [] for one in range(30): t = threading.Thread(target=worker) task.append(t) for one in task: one.start() for one in task: one.join()
这样我们确实是解决了多线程数据安全的问题。但是这时候如其它线程要获得Singleton实例的线程还是必须等待,锁的存在降低了效率,有性能损耗。
总结, 我自己会有选择性的使用单例模式,把单例模式封装成一个装饰器使用起来很方便。另外对于数据库,尤其是mysql,建议不要使用单例模式。
直接把类当模块导入是不是也是单例模式?