Python设计模式-单例模式

8次阅读

共计 1826 个字符,预计需要花费 5 分钟才能阅读完成。

什么是单例模式?

单例模式是一种写程序的方式, 用单例模式设计的类, 无论你去实例化多少次, 得到的都是同一个实例, 一般我们设计的类每次实例化都会生成不同的实例, 但是单例模式就是反其道而行之, 就像下面这样:

上图中的 ClassA 和 ClassB 都是采用的 单例设计模式, 而 ClassC 没有采用单例设计模式

我们可以清晰的看到 ClassA 的两个不同的实例在内存中的地址是相同的, 也就是说两次实例化得到的对象是同一个对象,ClassB 和 ClassA 也是一样的, 因为都采用了单例设计模式, 而 ClassC 因为没有采用单例设计模式所以他的两个实例对象指向不同的内存地址, 也就是说两次实例化得到的是两个不同的对象.

为什么需要单例模式?

要弄清楚为什么需要单例模式, 首先需要知道单例模式提供了哪些优秀的特性?

单例模式提供的最为优秀的特性就是: 单例模式可以允许你在程序的任何地方访问某个特定的对象

通过单例设计模式, 你可以在不定义全局变量的情况下, 在程序的任何地方访问你所指定的对象, 单例模式所提供的功能和全局变量是一样的, 但是通过单例模式设计, 你就可以在无需牺牲代码可读性和安全性的前提下完成和全局变量完全一样的功能. 单例模式吸收了全局变量的优点摒弃了全局变量的缺点, 是替代可恶全局变量不二的选择.

在上面的例子中我们可以看到无论实例化多少次 ClassA 得到的都是同一个对象, 如果这个类处于一个比较大的工程中, 在这个工程中的任何位置实例化 ClassA 得到的都是同一个对象, 这不就是全局变量吗, 但是和全局变量不同的是通过单例模式产生对象的代码更加的易读, 而且这种面向对象的编程方式可以确保 ClassA 所产生的对象只能被对象自身的方法所操作, 这样就更加的安全, 而且你可以通过获取实例的方法对返回对象的行为进行更多的限制.

为什么需要单例模式? 本质上是因为人们需要全局变量, 需要一个更加好用更加安全的全局变量, 单例模式的出现解决了全局变量的现有问题, 所以人们才需要单例模式

单例模式和全局变量的区别?

单例模式像极了全局变量, 但是单例模式毕竟不是实现全局变量, 除了上述所说的异同点之外, 通过单例模式产生的对象和全局变量还有一个明显的区别就是全局变量一旦定义就绝对不会再发生改变, 但是单例模式虽然说每次返回的都是一个固定的对象, 但这个固定的对象还是可以通过单例类自身的一些方法去更改的, 所以单例模式产生的对象和全局变量比起来只能说是相对固定的.

单例模式如何实现?

任何一门语言要想实现单例模式, 可能都有很多的实现方法, 但是实现思路大同小异, 肯定都是在第一次生成实例的时候就直接把实例给存储到某个地方, 然后在下一次实例化的时候直接返回这个事先被存储起来的实例, 而不是重新去实例化返回一个新的实例.

基于装饰器的实现

Python 实现单例模式一个比较优雅的实现方式就是通过装饰器去实现, 如下所示:

def singleton(cls):
    instances = {}
    def getinstance(*args,**kwargs):
        if cls not in instances:
            instances[cls] = cls(*args,**kwargs)
        return instances[cls]
    return getinstance

@singleton
class ClassA:
    pass

@singleton
class ClassB:
    pass

class ClassC:
    pass

aa=ClassA()
aaa=ClassA()

bb=ClassB()
bbb=ClassB()

cc=ClassC()
ccc=ClassC()

上面的例子我们可以看到 singleton 是一个装饰器函数, 通过闭包的原理让其内部的 instances 变量的生命周期和全局变量等同, 然后把被装饰的类第一次实例化生成的对象直接存储在 instances 中, 在取对象的时候直接从在 instances 字典中找到事先存储好的对象返回, 就是通过这样的方式实现单例的.

单例模式的实现方式还有很多种: 比如通过类属性实现, 通过元类实现等多种方式, 甚至每一种实现可能都有自己特定的应用场景, 但是我觉得通过装饰器实现最为优雅, 本着少就是多的原则, 其他的实现方式我就不再赘述, 如果对其他的实现方式感兴趣可以在 早睡蟒 公众号后台回复 跬蟒 加我微信 (备注好公司岗位) 交流沟通.

如果感觉本篇内容还不错, 微信的朋友请点个在看和赞, 其他平台的朋友可以 (近距离) 扫描下方的二维码关注我的公众号 早睡蟒 更多优质原创无广告内容等你来看.

正文完
 0