一、要求
设计一个类,只能生成该类的一个实例
二、相关概念
单例模式的概念:单例模式是设计模式的一种,一个类只有一个实例。
new 方法: new 方法创造一个类的实例,最后需要返回相应类的实例( init 方法实现初始化)。新式类开始实例化时,new()方法会返回cls(cls指代当前类)的实例,然后该类的 init()方法作为构造方法会接收这个实例(即self)作为自己的第一个参数,然后依次传入new ()方法中接收的位置参数和命名参数。
单例模式类的特殊性:无论使用多少个变量初始化实例,指向的都是同一个,一改多改。
is 和==的区别:==比较两者的内容/值value是否一致,is比较两者是否完全相同,这部分仍然不是很明白
类装饰器:用来修饰函数或类,将要装饰的对象作为参数,定义另一个函数进行操作,返回装饰过的函数。应用场合:当某个功能能够用在多个函数上。
三、思路
方法一:使用new方法,在创建类实例时,通过类变量_instance判断是否实例化过,返回类的实例,因为类实例(new)被绑定到类变量_instance上,所以返回的是类变量cls._instance
方法二:单例——创建的所有实例拥有相同的属性——共享属性——属性__dict__指向同一个字典_state
方法三:对类singleton建立装饰器,执行singleton()时相当于执行了singleton()=decorate(singleton),每执行一次singleton()判断一下,字典instances中是否有该类对象cls,无就添加,有就调出字典中存储的对象
方法四:将单例单独构建一个模块,利用import只能导入一次的性质
四、程序
方法一:new cls. _instance 程序2.1
class singleton1(object):#建立一个单例的类,单例的基类是object def __new__(cls,*args,**kwargs):#三参数:正在实例化的类,tuple类型多个无名参数,dict类型多个关键字参数 if not hasattr(cls,'_instance'):#hasatter检查cls是否有_instance属性,若有说明已经实例化过了 orig=super(singleton1,cls)#使用supper获得父类名,此处为object cls._instance=orig.__new__(cls,*args,**kwargs)#要得到当前类的实例,需要在__new__中调用父类的__new__ #在新式类的__new__中,可以调用除去自身(死循环)及经典类(无__new__)的__new__方法 return cls._instance#如果不返回当前类的实例cls,而是返回其他类的实例,那么当前类的初始化init不执行,转而调用对应类的构造方法 class MyClass(singleton1):#构造Myclass类的作用是为了说明单例类属性一致,一改多改 a=1 def main(): one=MyClass() two=MyClass() print(one.a) two.a=3 print(one.a) print(id(one),id(two))#返回对象内存地址 print(one==two,one is two) if __name__=='__main__': main()
方法2:共用属性 程序2.2
class singleton2(object): _state={} def __new__(cls, *args, **kwargs): orig=super(singleton2, cls) ob=orig.__new__(cls,*args,**kwargs) ob.__dict__=cls._state#__dict__是一个字典,键是属性名,值为属性值 return ob class Myclass(singleton2): a=1 def main(): one=Myclass() two=Myclass() print(one.a) two.a=3 print(one.a) print(one==two,one is two) print(id(one),id(two)) print(id(one.__dict__),id(two.__dict__)) if __name__=='__main__': main()方法三:类装饰器 程序2.3
def decorate(cls): instances = {} def getinstance(): if cls not in instances: instances[cls] = cls() return instances[cls] return getinstance#这里不能有() @decorate class singleton(object): a = 1 def main(): one = singleton() two = singleton() print(one.a) two.a = 3 print(one.a, two.a) print(id(one), id(two))#一致 if __name__ == '__main__': main()
方法四:import模块 程序2.4 程序 MySingleton
# MySingleton.py class singleton(): def __init__(self,a): self.value1=a mysingleton=singleton(2)
#2.4 from MySingleton import mysingleton one=mysingleton two=mysingleton print( one is two , one==two)
五、参考资料
new的思想:
http://www.jb51.net/article/85724.htm
*args,**kwargs:
https://zhidao.baidu.com/question/367559039025445444.html
is 与==:
https://www.cnblogs.com/CheeseZH/p/5260560.html
https://www.cnblogs.com/kiko0o0/p/8135184.html
类装饰器:
http://blog.csdn.net/majianfei1023/article/details/45001021