1. 程式人生 > >python設計模式之單例模式(二)

python設計模式之單例模式(二)

__new__ 有意 {} 開發人員 sta 字典 spa 出現 創建

上次我們簡單了解了一下什麽是單例模式,今天我們繼續探究。
上次的內容點這 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設計模式之單例模式(二)