20180321剑指offer题2——单例模式SingleTon

一、要求

    设计一个类,只能生成该类的一个实例

二、相关概念

单例模式的概念:单例模式是设计模式的一种,一个类只有一个实例。

   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

猜你喜欢

转载自blog.csdn.net/weixin_41819299/article/details/79641179