上次我们简单了解了一下什么是单例模式,今天我们继续探究。
上次的内容点这 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. poj1065-Wooden Sticks

    题目 有很多小木棍需要机器处理.每个小木棍有重量和长度两个属性.不断把小木棍放入机器中,如果小木棍\(a\)放完后放入小木棍\(b\),那么如果\(a.weight<=b.weight\ and ...

  2. P1278 单词游戏

    题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...

  3. 51nod 1215 数组的宽度&poj 2796 Feel Good(单调栈)

    单调栈求每个数在哪些区间是最值的经典操作. 把数一个一个丢进单调栈,弹出的时候[st[top-1]+1,i-1]这段区间就是弹出的数为最值的区间. poj2796 弹出的时候更新答案即可 #inclu ...

  4. ucenter通信实现同步登录、同步退出(详细)

    首先,需要去官网下载一个ucenter的包.然后解压下来. 先把ucenter/ucenter这个文件夹复制到你的项目根目录下改名为uc_server;(这里只是我建议修改,以便于我下面写的配置); ...

  5. adb 进入 recovery adb 进入 bootloader

    重启到Recovery界面 adb reboot recovery重启到bootloader界面 adb reboot bootloader adb wait-for-device #等待设备 adb ...

  6. Linux之异步通知20160702

    异步通知,主要说的是使用信号的方式,同时使用信号也是实现进程之间通信的一种方式. 多的不说,我们直接看代码: 首先应用程序的: #include <sys/types.h> #includ ...

  7. c++11新特性之nullptr

    在c++11中,nullptr可完全代替NULL.  然而NULL和nullptr还是稍有不同,NULL可被转化为int类型,而nullptr不能.因此nullptr对NULL在进行模板推导或者函数重 ...

  8. HDU 1074状压DP

    Doing Homework Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)To ...

  9. LightOJ 1375 - LCM Extreme 莫比乌斯反演或欧拉扩展

    题意:给出n [1,3*1e6] 求 并模2^64. 思路:先手写出算式 观察发现可以化成 那么关键在于如何求得i为1~n的lcm(i,n)之和.可以知道lcm(a,b)为ab/gcd(a,b) 变换 ...

  10. outer的使用

    outer就是一个标签,java语言中根本没有此关键字,因此outer也可以用其它的词来代替 java中的标签就是一个紧跟着英文冒号(:)的标识符.与其他语言不同的是,java中的标签只有放在循环语言 ...