一、了解單例模式
確定類有且隻有一個特定類型的對象,并提供全局通路點,單例模式通常用于下列情形,例如日志記錄或資料庫操作等,避免對同一資源請求的互相沖突。
單例的模式的意圖如下:
- 確定類有且隻有一個對象被建立。
- 為對象提供一個通路點,以使程式可以全局通路該對象。
- 控制共享資源的并行通路。
實作單例模式的一個簡單方法是,使構造函數私有化,并建立一個靜态方法來完成對象的初始化。這樣,對象将在第一次調用時建立,此後,這個類将傳回同一個對象。然後在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/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須在文章頁面給出原文連接配接,否則保留追究法律責任的權利。