上次我们简单了解了一下什么是单例模式,今天我们继续探究。
上次的内容点这 python设计模式之单例模式(一)

上次们讨论的是GoF的单例设计模式,该模式是指:一个类有且只有一个对象。通常我们需要的是让实例共享一个相同的装态 比如数据库连接。Alex Martelli的建议的是开发人员应该关注状态和行为,而不是同一性,因此它也被称为Monostate(单态)模式。

Monostate单例模式的概念

先说说 MonoState 这个单词的意思,设计模式的名字都是很有意思的,因为为了方便交流、记忆,所以设计模式的命名都对 该模式的意图进行了表述。 Mono 是一个词根,英语中 Mono,Mon 都表示的是 1 的意思, state 意思为 " 状态 " 。 MonoState 的意思就是 " 单一的状态 ",MonoState 并不限制创建对象的个数,但是它的状态却只有一个状态

Monostate单例模式的使用

我们知道在python中,__dict__是用来存储对象属性的一个字典,其键为属性名,值为属性的值。所以下面我们可以使用dict来存储一个类所有对象的状态。来看下面这个例子:

class useDict:
    __state={"name":"cxa"}
    def __init__(self):
        self.age=27
        self.__dict__=self.__state
m=useDict()
m1=useDict()
m.age=23
print(m)
print(m1)
print(m.__dict__)
print(m1.__dict__)

运行以后输出结果。

<__builtin__.useDict instance at 0x7f78ceacc098>
<__builtin__.useDict instance at 0x7f78ceacc128>
{'age': 23, 'name': 'cxa'}
{'age': 23, 'name': 'cxa'}

首先我们看结果 我们发现每次对useDict实例化都会创建一个新的对象,然后我们通过m修改了age属性的值后,m1的age属性值也发生了变化。
除此之外我们还可以使用__new__方法本身来实现。

class useNew(object):
    _state={}
    def __new__(cls,*args,**kwargs):
        obj=super(useNew,cls).__new__(cls,*args,**kwargs)
        obj.__dict__=cls._state
        return obj
a=useNew()
a1=useNew()
a.x=3
print(a)
print(a1)
print(a.__dict__)
print(a1.__dict__)

下面是输出结果

<useNew object at 0x7f78ceb873d0>
<useNew object at 0x7f78ceb87b50>
{'x': 3}
{'x': 3}

两种写法的效果是一样的。

元类的实现方式

元类是一个类的类,这就意味着该类是它的元类的实例。对于已经存在的类来说,当需要创建对象的时候,将调用python的特殊方法__call__,我们可以通过使用元类的__call__方法,来控制一个对象的实例化,具体看下面的例子
一个数据库连接的例子

import pymysql
class MetaSingleton(type):
    _inst={}
    def __call__(cls,*args,**kwargs):
        if cls not in cls._inst:
            cls._inst[cls]=super(MetaSingleton,cls).__call__(*args,**kwargs)
        return cls._inst[cls] class MysqlDb(metaclass=MetaSingleton):
     connection=None
     def conn(self):
        if self.connection is None:
             self.connection= pymysql.connect(host='127.0.0.1', port=3306, user='root',
             passwd='Aa1234', db='user', charset='utf8mb4')
             self.cursor=self.connection.cursor()
        return  self.cursor
d1=MysqlDb().conn()
d2=MysqlDb().conn()

单例模式的缺点

介绍了这么长时间的单例模式,也许你会有疑问,那单例模式有什么缺点呢?
虽然单例模式的效果很好但是依然存在一些问题,因为单例具有全局访问权限,所以可能出现以下问题:

  • 全局变量可能在某个地方被改了但是不知道。(比如之前的那个使用__dict__的例子)。
  • 可能会对同一个对象创建多个引用。由于单例只创建一个对象,因此这种情况下会对一个对象创建对个引用。
  • 所有依赖于全局变量的类都会由于一个类的改变而紧密耦合为全局数据,从而可能在无意中影响另一个类。

到此为止,我们就把单例模式的相关内容介绍完了,后续也许会写关于其他设计模式的相关文章,如果你喜欢的话,转发到朋友圈和小伙儿们一起分享吧。

python设计模式之单例模式(二)的更多相关文章

  1. python设计模式之单例模式(一)

    前言 单例模式是创建模式中比较常见和常用的模式,在程序执行的整个生命周期只存在一个实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常用创建模式总结(二) python ...

  2. python设计模式之单例模式(转)

    设计模式之单例模式 单例设计模式是怎么来的?在面向对象的程序设计中,当业务并发量非常大时,那么就会出现重复创建相同的对象,每创建一个对象就会开辟一块内存空间,而这些对象其实是一模一样的,那么有没有办法 ...

  3. Python设计模式之单例模式

    1.由于语言的特性不同,设计模式的实现方式和实现难度也会不同 2.有的模式已经在语言内置了,比如迭代器模式. 3.单例模式可以直接用模块级变量来实现 4.普通工厂模式可以直接通过传入"类名& ...

  4. python设计模式之单例模式(一)

    单例设计模式的概念: 单例设计模式即确保类有且只有一个特定类型的对象,并提供全局访问点.一般我们操作数据库的时候为了避免统一资源产生互相冲突,创建单例模式可以维护数据的唯一性. 单例模式的特性: 确保 ...

  5. python设计模式之--单例模式

    python的单例模式就是一个类的实例只能自始自终自能创建一次.应用场景比如说数据库的连接池. #!/usr/bin/env python # coding=utf- class Foo(object ...

  6. Python设计模式中单例模式的实现及在Tornado中的应用

    单例模式的实现方式 将类实例绑定到类变量上 class Singleton(object): _instance = None def new(cls, *args): if not isinstan ...

  7. 【python 设计模式】单例模式

    单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在.当你希望在整个系统中,某个类只能出现一个实例时,单例对象就能派上用场. 比如,某 ...

  8. python 设计模式之 单例模式

    单例模式是做为"全局变量"的替代品出现的.所以它具有全局变量的特点:全局可见.贯穿应用程序的整个生命期,保证在程序执行中,某个类仅仅存在一个实例,所以通常不希望类中的构造函数被调用 ...

  9. python 设计模式之单例模式 Singleton Pattern

    #引入 一个类被设计出来,就意味着它具有某种行为(方法),属性(成员变量).一般情况下,当我们想使用这个类时,会使用new 关键字,这时候jvm会帮我们构造一个该类的实例.这么做会比较耗费资源. 如果 ...

随机推荐

  1. Qt快速入门学习笔记(画图篇)

    1.Qt中提供了强大的2D绘图系统,可以使用相同的API在屏幕和绘图设备上进行绘制,它主要基于QPainter.QPaintDevice和QPaintEngine这三个类.其中QPainter用来执行 ...

  2. shell脚本学习—条件测试和循环语句

    条件测试 1. 条件测试:test [ 命令test或[可以测试一个条件是否成立,如果测试结果为真,则该命令的Exit Status为0,如果测试结果为假, 则命令的Exit Status为1(注意与 ...

  3. springboot2.0 如何异步操作,@Async失效,无法进入异步

    springboot异步操作可以使用@EnableAsync和@Async两个注解,本质就是多线程和动态代理. 一.配置一个线程池 @Configuration @EnableAsync//开启异步 ...

  4. Android ListView的优化

    最近的项目中有通讯录这个模块,里面的通讯录涉及的联系人数量很大,导致在加载页面的时候有点卡,所以就必须得进行优化,优化的最终实现理论是什么?就是让ListView一次性加载的数据较少,后续根据用户操作 ...

  5. JavaScript截取中英文字符串

    有时在显示某段文字的时候,可能会太长,影响我们页面的显示效果.如果仅是英文,那么我们可以用String.substring(start, end)函数就已经够用了.但是通常我们都会遇到既有英文,又有汉 ...

  6. setTimeout()的应用

    错误写法:setTimeout(window.close(),5000); 正确写法:setTimeout(window.close,5000); 或者 setTimeout(function(){ ...

  7. selenium - 获取断言信息

    断言:通过脚本提取相应元素的数值,将实际结果与预期结果进行比较.通常获取title,URL,text等信息进行断言. from selenium import webdriver from time ...

  8. unix网络编程-套接字编程 读书笔记

    1. 学习总结(目前只看了前6章):http://note.youdao.com/noteshare?id=2a0c29f5feeddd8f6f390427f0d67114 2. 课后习题 第一章 h ...

  9. uboot启动原理

    1.裸机运行程序时一般情况下程序代码小于16KB将其下载地址设置到BL1的起始地址.BL0会自动加载并执行BL1. 当程序大于16kB时无法直接运行. 例如UBOOT就大于16KB,执行的原理为.将程 ...

  10. rename 批量重命名

    使用背景,对规则文件名批量重命名 例如: Send_Message_20160802_01_log.log Send_Message_20160802_02_log.log Send_Message_ ...