单例模式

一、简介

 

 

      单例模式是一种常用的软件设计模式

      要点:

  • 一是某个类只能有一个实例
  • 二是它必须自行创建这个实例
  • 三是它必须自行向整个系统提供这个实例

      具体点说主要:

  • 一是单例模式的类只提供私有的构造函数
  • 二是类定义中含有一个该类的静态私有对象
  • 三是该类提供了一个静态的共有函数用于创建或获取它本身的静态私有对象

 

二、了解callable

  • callable() 函数用于检查一个对象是否是可调用
  • 对于函数、方法、lambda 函式、 类以及实现了 __call__ 方法的类实例, 它都返回 True

       下面我们来看一段代码:

       

def add(x,y):
    return x+y

class Myclass(object):
    pass

class Myclass2(object):
    def __call__(self,*args,**kwargs):
        pass

#执行:
print(callable(add))
print(callable(Myclass()))
print(callable(Myclass2))

#输出结果:
True
False
True
#执行:
Myclass2()()
add(1,2)

#输出结果没有报错
#执行:
Myclass()()

#执行结果:
TypeError: 'Myclass' object is not callable

总结:不难看出一个对象中有callable属性,表明该对象能够被调用(也就是对象后面可以加“()”)

 

   

三、初识单例模式

在了解单例模式之前,我们先了解下"__init__"和"__new__"的区别:

  • 在基础类object中,new被定义成了一个静态方法,并且需要传递一个参数cls
  • Cls表示需要实例化的类,此参数在实例化时由Python解析器自动提供

下面我们看一段代码:

class MyClass(object):
    def __init__(self):
        print("init is running ...")
    #重写__new__方法,并没创建对象
    def __new__(cls,*args,**kwargs):
         pass

#执行:
print(type(Myclass()))

#输出结果:
<class 'NoneType'>

#############分隔线################
class MyClass(object):
    def __init__(self):
        print("init is running ...")

#执行:
print(type(Myclass()))

#输出结果:
<class '__main__.MyClass'>

############分割线#################
class MyClass(object):
    def __init__(self):
        print("init is running ...")

    def __new__(cls,*args,**kwargs):
    #创建对象,分配内存
        print("new is running...")
        obj = super().__new__(cls)
        return obj

#执行:
print(type(Myclass()))

#输出结果:
<class '__main__.MyClass'>

总结:不难看出的,一个类中默认包含new方法,若将new重写(不按原始的方式)将不能创建对象

__new__方法创建对象,分配内存

__init__方法负责将类实例化(初始化)

 

下面我们通过一段代码用__new__实现单例模式:

class Myclass(object):
    obj = None  #定义对象初始值为空

    def __new__(cls,*args,**kwargs):
        if cls.obj is None:
            cls.obj = super().__new__(cls)  #创建对象
        return cls.obj
#执行:
 a=Myclass()
 b=Myclass()
 print(id(a))
 print(id(b))

#输出结果:
2281358467144
2281358467144

 

 总结:从上述代码输出结果不难看出,虽然两次调用了Myclass(),但是只实例化了一次

 

四、单例模式基础及应用

下面我们将通过装饰器来实现单例模式:

 

posted @ 2020-12-11 18:03  然后呢。。。  阅读(65)  评论(0编辑  收藏  举报