單例模式(python)

什麼是單例模式:
單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。
比如,系統的配置信息,在整個項目種很多地方會使用到,但是配置信息是不會在項目種被更改的,如果重複的創建配置信息的對象的化,會嚴重的浪費內存資源,如果能只存在一個對象,那就好了,由此而生的單例模式。
單例模式的創建有以下幾個方式:
1.做成一個模塊。
例:
在一個a.py文件中寫好配置文件的信息的類方法,並給它創建了一個實例對象。再項目中要使用的時候,就直接 from a import singleton 把這個實例對象導進來。

class Singleton(object):
    def test(self):
        pass
singleton = Singleton()

2.利用裝飾器。
例:
利用了下閉包。 在創建test方法的時候,執行singleton(test)語句。
外層函數調用內層函數,內層函數使用外層函數中的test對象。用一個字典instances 來判斷是否已經創建了實例,若沒有則創建test的實例對象,並把test類 和 test實例對象存到字典中,返回test;若已經創建,則直接返回字典中存儲的test實例對象。(這裏在多線程中出現資源搶奪問題,可以加鎖解決。)

def singleton(cls):
    instances = {}
    def singleton_in(*args, **kwargs):
        if cls not in instances:
            instances[cls] = cls(*args, **kwargs)
    	return instances[cls]
	return singleton_in
	
@singleton    #這句話就大致可以理解 test()=singleton(test)
class test(object):
    pass
a=test()
b=test()

3.重寫類的__new__方法。
例:
new :必須得有一個參數,表示要實例化的類,必須得有返回值,返回值是實例化出來的實例。類被實例化時,是先執行__new__方法,再執行__init__方法,__init__方法中的self是__new__方法中返回的實例對象。
代碼中用__instance的類屬性做控制,這個屬性存儲的是第一次實例化的對象。
裏面有with Singleton.__lock ,上下文資源管理器來給判斷語句加上鎖。這樣就可防止多線程中的資源搶奪的問題,造成創建了多個實例。

class Singleton(object):
    __lock = threading.Lock()

    def __init__(self):
        pass


    def __new__(cls, *args, **kwargs):
        if not hasattr(Singleton, "__instance"):
            with Singleton.__lock:
                if not hasattr(Singleton, "__instance"):
                    Singleton.__instance = object.__new__(cls)  
        return Singleton.__instance

4.利用元類機制(原理和上一種一樣)
metaclass
metaclass=SingletonType這句話的意思是創建Test類用SingletonType方法來創建, 即執行SingletonType() 這個語句,調用__call__方法。
Test創建一個實例對象後,以後再創建時,只是讓變量b指向實例對象的地址,也不會再執行__init__的方法,即b = Test()中 不傳參數也可以執行。

import threading

class SingletonType(type):
    __lock = threading.Lock()
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "__instance"):
            with SingletonType.__lock:
                if not hasattr(cls, "__instance"):
                    cls.__instance = super(SingletonType,cls).__call__(*args, **kwargs)
        return cls.__instance

class Test(metaclass=SingletonType):
    def __init__(self,name):
        self.name = name
    def single(self,aaa):
        print('唱歌',aaa)

    def happy(self):
        print('唱歌')    

a = Test('1111')
b = Test()
a.single('山無棱')
b.single('天地合')
print(id(a))
print(id(b))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章