一、理解单例模式
确保类有且只有一个特定类型的对象,并提供全局访问点,单例模式通常用于下列情形,例如日志记录或数据库操作等,避免对同一资源请求的相互冲突。
单例的模式的意图如下:
- 确保类有且只有一个对象被创建。
- 为对象提供一个访问点,以使程序可以全局访问该对象。
- 控制共享资源的并行访问。
实现单例模式的一个简单方法是,使构造函数私有化,并创建一个静态方法来完成对象的初始化。这样,对象将在第一次调用时创建,此后,这个类将返回同一个对象。然后在python中构造函数是无法私有化的,因此需要使用其他方式进行创建。
二、实现
1、基于__new__方法创建单例
__new__方法是先于__init__方法执行,主要用于创建对象,在完成单例模式时,主要是:只允许单例类生成一个实例;如果已经有一个实例了,重复提供同一个对象。这样保证每一次实例化类只提供一个对象。
class SingleTon(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls,"instance"):
cls.instance = super(SingleTon,cls).__new__(cls, *args, **kwargs)
return cls.instance
s=SingleTon()
print(s)
s1=SingleTon()
print(s1)
###输出###########
#<__main__.SingleTon object at 0x0000000000656828>
#<__main__.SingleTon object at 0x0000000000656828>
上面是通过覆盖__new__的方法创建对象的,对象s就是由__new__方法创建的,但是在创建之前会先检查cls中是否已经有一个对象(instance就是对象),如果没有就创建一个实例,如果已经存在,就将已经存在的实例进行返回。
s1对象在使用__new__方法创建时,会通过hasattr属性检查是否已经存在对象实例,此时已经存在s的实例,所以将s的实例地址返回给s1。
2、基于getInstance创建单例
为了避免对内存造成浪费,直到需要实例化该类的时候才将其实例化,所以用getInstance来获取该对象。
class SingleTon(object):
_instance=None
def __init__(self):
if not SingleTon._instance:
print("没有创建对象")
else:
print("已经创建对象",self.getInstance())
@classmethod
def getInstance(cls):
if not cls._instance:
cls._instance=SingleTon()
return cls._instance
s=SingleTon() #并没有创建对象
SingleTon.getInstance() #创建了对象
s1=SingleTon() #对象已经存在
#####################输出############
#没有创建对象
#没有创建对象
#已经创建对象 <__main__.SingleTon object at 0x0000000000676898>
当执行s=SingleTon()执行了__init__方法,然而并没有创建对象,真正创建对象的是在SingleTon.getInstance(),这样每次在获取对象时就通过这个静态方法获取,不需要使用__new__方法来创造对象。
3、基于模块级别的单例模式
python导入模块的行为决定了每一个模块都是单例,因为,python在导入模块时会检查模块是否已经导入,如果没有导入,它会进行导入并且实例化,如果已经导入则会返回该模块的对象。
因此,当模块被导入的时候,它就会被初始化。然而,当同一个模块被再次导入的时候,它不会再次初始化,因为单例模式只能有一个对象,所以,它会返回同一个对象。
使用方式:
- 在一个py文件中写入类并且实例化
class AdminSite(object):
def __init__(self):
pass
site=AdminSite()
- 在另一个py文件中导入该类对象
from base_moudle.base import site
print(site) #<base_moudle.base.AdminSite object at 0x0000000000D3AE80>
4、基于元类创建单例
在python中 一切皆对象,由class关键字创建的类也应该是一个对象,那么,既然是对象,它也应该是由类来创建的,这个类就叫做元类(type)。当通过一个元类来创建一个类时,比如当使用类A创建一个类时,pytno通过A=type(name,bases,dict)创建它。
- name:这是类的名称。
- base:这是基类。
- dict:这是属性变量。
比如使用元类创建一个类:
class MyString(type):#继承type才是一个元类
def __call__(self, *args, **kwargs):
return type.__call__(self,*args, **kwargs)
class String(metaclass=MyString):
def __init__(self,x):
self.x=x
s=String("abggd")
当需要创建对象时,将调用__call__方法,也就是说对象()触发__call__方法的执行,当对String类进行实例化时,实际是MyString元类的对象进行实例化,这会触发__call__方法的运行,它的返回值就是实例化后的结果的接收值,这意味者元类控制着对象的实例化。
同样的,也就可以利用以上的思路,进行单例模式的实现,为了控制类的创建和初始化,元类将覆盖__new__以及__init__方法。
class MetaSingleTon(type):
_instance={}
def __call__(self, *args, **kwargs): #self指代的是传过来的类 AdminSite
if self not in self._instance:
self._instance[self]=super(MetaSingleTon,self).__call__( *args, **kwargs)
return self._instance[self]
class AdminSite(metaclass=MetaSingleTon):
pass
a1=AdminSite() #相当于执行元类中的__call__方法,__call__的返回值是什么a1就是什么
print(a1)
a2=AdminSite()
print(a2)
########输出###########
#<__main__.AdminSite object at 0x0000000000666CC0>
#<__main__.AdminSite object at 0x0000000000666CC0>
单例模式可以应用于多种场景,这里提供应用于数据库层面的,保证数据库操作一致性以及提高内存利用率。

import pymysql
class MetaSingleTon(type):
_instance={}
def __call__(self, *args, **kwargs): #self指代的是传过来的类 AdminSite
if self not in self._instance:
self._instance[self]=super(MetaSingleTon,self).__call__( *args, **kwargs)
return self._instance[self]
class DataBase(metaclass=MetaSingleTon):
connection=None
def connect(self):
if self.connection is None:
self.connection=pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='root', db='test', charset='utf8')
self.cursor=self.connection.cursor()
return self.cursor
def excute(self,sql):
pass
def close(self):
self.connect().close()
self.connection.close()
db1=DataBase()
db2=DataBase()
print(db1)
print(db2)
#########################输出################
#<__main__.DataBase object at 0x0000000000DF6A90>
#<__main__.DataBase object at 0x0000000000DF6A90>
操作数据库
5、Monostate单例模式
它与Singleton单例模式是有不同之处的,Singleton关注的是一个类有且只有一个对象,而Monostate关注的则是一个类不管有多少个对象,所有的对象只有一个状态,因此它也被称为单态模式。那么它是如何实现这种模式呢?
class Borg:
__shared_state={}
def __init__(self):
self.x=3
self.__dict__=self.__shared_state
b1=Borg()
b2=Borg()
b2.x=4
print(b1.__dict__)
print(b2.__dict__)
######输出###########
#{'x': 4}
#{'x': 4}
将__shared_state变量作为一个中间变量,并且赋值给python中存储类所有对象状态的__dict__变量,这在实例后,会产生两个不同的对象,但是b1.__dict__和b2.__dict__都指向了__shared_state的内存地址。
另外还可以通过__new__来实现单态模式:
class Borg:
__shared_state = {}
def __new__(cls, *args, **kwargs):
obj=super(Borg,cls).__new__(cls, *args, **kwargs)
obj.__dict__ = obj.__shared_state
return obj
作者:iveBoy
出处:http://www.cnblogs.com/shenjianping/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保留追究法律责任的权利。