看,python單例設計模式

要了解單例設計模式,我們首先要了解什麼是設計模式。

設計模式:通俗的講就是每一個模式都是我們在代碼中不斷要遇到的問題,通過分析,然後分類這些問題,進行代碼的設計和經驗的總結。爲了就是可重用代碼,讓代碼的設計更容易被他人理解,保證了代碼的可靠性。

單例設計模式:目的就是讓類創建的對象,在系統中只有唯一的實例,每一次執行類名()返回的對象,內存地址是相同的,這樣就可以讓軟件更加的有秩序的運行,也節省了內存。

應用對場景:

回收站(在系統的運行中,回收站一直存在僅有的一個實例)

任務管理器(在系統中只能打開一個任務管理器)

Django框架中的配置文件讀取,也是單例模式,因爲配置文件是共享的資源

還有一些軟件也是遵循這種方法音頻類的軟件基本上都是單例模式,在這就不一一列舉了。

下面我們就以回收站做一個簡單的實例:

在使用單例前我們還要理解__new__這個python的內置方法。

當我們創建一個類的時候,我們基本上用的最常用的是__init__初始化的方法,在這個方法中可以定義實例的屬性。

但是在類中創建每個對象時,都要給這個對象分配空間,這個任務就交給了__new__方法

 

所以當我們要寫單例模式的時候我們首先要對__new__方法進行重構。

下面我們先實現這個__new__方法

class Trash(object):
    def __new__(cls, *args, **kwargs):
        print("new方法被調用")

    def __init__(self):
        print('開始收集')

a = Trash()
print(a)

---------------------->
new方法被調用
None

通過上面的代碼我們看出__new__方法中有三個參數,第一個參數就是哪個類調用就傳遞哪個類,現在傳遞的就是Trash類。

後面兩個參數可以看我的這篇博客(https://blog.csdn.net/qq_42992704/article/details/104244084),另外我們可以看出我們返回的結果中沒有初始化的值。這是因爲我們沒有分配空間和返回對象的引用,只是在創建這個對象時,new的方法被自動調用了。

要怎樣分配空間和返回對象引用呢?

在這我們可以調用object基類中的__new__的默認方法,它已經可以爲對象分配空間。

class Trash:
    def __new__(cls, *args, **kwargs):
        print("new方法被調用")
        space = super().__new__(cls)
        return space

    def __init__(self):
        print('開始收集')

a = Trash()
print(a)

---------------------->
new方法被調用
開始收集
<__main__.Trash object at 0x00000271EDFD6BA8>

 

有上面我們看的出通過繼承父類的new方法,便可以爲a這個實例對象創建空間。

return space  由sapce接收了父類方法返回的結果,然後在返回這個變量,__new__的方法也就重構完成。這樣我們就可以接受到實例中的屬性。

講到這我們也只是介紹了怎樣改造__new__這個方法,    下面便會引出怎樣將許多軟件回收到垃圾桶裏

class Trash:
    def __new__(cls, *args, **kwargs):
        print("new方法被調用")
        space = super().__new__(cls)
        return space

    def __init__(self):
        self.name = name
        print('卸載完成')

mooc = Trash()
dingding= Trash()
xuexitong = Trash()
print(mooc,dingding,xuexitong)
---------------------->
new方法被調用
卸載完成
new方法被調用
卸載完成
new方法被調用
卸載完成
<__main__.Trash object at 0x000002B99B946BA8> <__main__.Trash object at 0x000002B99B946B70> <__main__.Trash object at 0x000002B99B946BE0>

通過上面的代碼我們當我們創建三個實例對象的時候,在Trash類中每次都會創建一個新的內存。對於這類都是屬於同一類的對象來說,顯然這樣是我們不希望的。所以我們稍微改進一下,先呈上。

class Trash:
    space = None
    def __new__(cls, *args, **kwargs):
        if cls.space is None:
            print("new方法被調用")
            cls.space = super().__new__(cls)
        return cls.space

    def __init__(self):

        print('卸載完成')

mooc = Trash()
dingding= Trash()
xuexitong = Trash()
print(mooc,dingding,xuexitong)
--------------------------->
new方法被調用
卸載完成
卸載完成
卸載完成
<__main__.Trash object at 0x0000020C7A636BA8> <__main__.Trash object at 0x0000020C7A636BA8> <__main__.Trash object at 0x0000020C7A636BA8>

在改進中,我們分析了我們所遇到的核心問題:多次調用的方法本質上還是一個對象,也就是唯一的實例。所以我們要對是否分配空間做一次判斷,如果已經創建空間,那麼在下次來的時候直接返回對象的引用。

-------------->引出了我們對單例的理解:在類創建對象的時候,不管你調用多少次類的方法,得到的結果永遠都是內存中唯一的實例。這就是我們單例所想要達到結果。

上面我們一直都是在改造__new__的方法實現單例,下面我們也應該對初始化的方法下手改造了。

class Trash:
    space = None
    flag = False
    def __new__(cls, *args, **kwargs):
        if cls.space is None:
            print("new方法被調用")
            cls.space = super().__new__(cls)
        return cls.space

    def __init__(self):
        if Trash.flag:
            return
        print('卸載完成')
        Trash.flag = True

mooc = Trash()
dingding= Trash()
xuexitong = Trash()
print(mooc,dingding,xuexitong)
------------------------------>
new方法被調用
卸載完成
<__main__.Trash object at 0x0000027B34966BE0> <__main__.Trash object at 0x0000027B34966BE0> <__main__.Trash object at 0x0000027B34966BE0>

我們可以定義一個類屬性,當我們在創建完對象的引入後,進行判斷讓初始化的方法也只進行調用一次。使用單例方法,可以大大節省了程序運行的時間,減少內存,更加明確類的分工。

see you !!!

發佈了42 篇原創文章 · 獲贊 29 · 訪問量 2621
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章