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

【Python】Python如何实现单例模式?

2014-05-24 22:53 435 查看
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在打印的任务;一个系统中只能有一个串口管理器或文件系统;一个系统只能有一个计时工具或ID生成器。如在window是中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪个才是真实的状态。

有时确保系统中某个对象的唯一性(即一个类只有一个实例)非常重要。如何保证只有一个实例并且这个实例能被访问到?建立一个全局变量可以保证对象随时都能被访问,但不能阻止实例化多个对象。一个更好的方法是让类自身负责保存它的唯一实例,并且让这个类保证没有其他实例创建。



单例模式的要素:

保证一个类只有一个实例。所有引用(实例、对象)拥有相同的状态(属性)和行为(方法);

保证这个类必须自行创建这个实例;

保证这个类向整个系统提供这个实例。

因此:

单例模式只提供私有的构造函数;

类中定义一个含有该类的静态私有对象

该类提供一个静态的共有的函数用于创建或获取它本身的静态私有对象

#共享属性,所谓单例就是所有引用(实例,对象)拥有相同的状态(属性)和行为(方法)
#同一个类的所有实例天然拥有相同的行为(方法),
#只需要保证同一个类的所有实例具有相同的状态(属性)即可
#而所有实例共享属性的最直接最简单的方法就是__dict__属性指向(引用)同一个字典

class Borg(object):
_state = {}
#单下划线开头,这个被常用于模块中,
#在一个模块中以单下划线开头的变量和函数被默认当作内部函数,
#如果使用 from a_module import * 导入时,这部分变量和函数不会被导入。
#不过值得注意的是,如果使用 import a_module 这样导入模块,
#仍然可以用 a_module._some_var 这样的形式访问到这样的对象。

def __new__(cls, *args, **kw):
#参数带一个星号,可以接受任意多的位置参数,带两个星号,可以接受任意多的关键字参数
ob = super(Borg, cls).__new__(cls, *args, **kw)
#绑定超类,调用超类object的__new__
#__new__(...)
#T.__new__(S, ...) -> a new object with type S, a subtype of T
#在这里返回object类的一个新对象
ob.__dict__ = cls._state
print(type(ob))
#__dict__包含了模块里可用的属性名-属性的字典;
#也就是可以使用模块名.属性名访问的对象
return ob

class Myclass(Borg):
a = 1

one = Myclass()
two = Myclass()

two.a = 3
print("a in one is: ", one.a)
print("identity of one is: ", id(one))
print("identity of two is: ", id(two))
print("is one equal to two? ", one == two)
print("__dict__ in one: ", one.__dict__)
print("__dict__ in two: ", two.__dict__)


输出:

>>> ================================ RESTART ================================
>>>
<class '__main__.Myclass'>
<class '__main__.Myclass'>
a in one is:  3
identity of one is:  38745136
identity of two is:  38242768
is one equal to two?  False
__dict__ in one:  {'a': 3}
__dict__ in two:  {'a': 3}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: