單列模式,裝飾器、new方法、類/靜態方法實現單列模式

1、單列模式

單例模式(Singleton Pattern)是一種經常使用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。html

如,某個服務器程序的配置信息存放在一個文件中,客戶端經過一個 Config 的類來讀取配置文件的信息。若是在程序運行期間,有不少地方都須要使用配置文件的內容,也就是說,不少地方都須要建立 Config 對象的實例,這就致使系統中存在多個 Config 的實例對象,而這樣會嚴重浪費內存資源,尤爲是在配置文件內容不少的狀況下。事實上,相似 Config 這樣的類,咱們但願在程序運行期間只存在一個實例對象。python

2、裝飾器實現單列模式

經過python的閉包原理,裝飾器能記得外層命名空間裝飾器原理參考本文數據庫

def single_decorator(cls):
    single = {}
    def wrapper(*args, **kwargs):
        if not single.get(cls.__name__):
            single[cls.__name__] = cls(*args, **kwargs)
        return single[cls.__name__]
    return wrapper

@single_decorator
class School:
    def __init__(self, name, addr, capital, represent):
        self.__name = name      #學校名
        self.__addr = addr      #地址
        self.__registered_capital = capital     #註冊資金
        self.__represent = represent        #法人表明


    def get_info(self):
        return "校名: {} 地址: {} 法人表明: {}".format(self.__name, self.__addr, self.__represent)

    @staticmethod
    def show():
        print(School._isxx)

ss= School('古天樂學校', '大涼山', '100.000', '古天樂')
ss2= School('施明德', '臺灣?', '1.000.000', '瞎寫的')
print('實例一id: %s'%(id(ss)))
print('實例二id: %s'%(id(ss2)))
print(ss.get_info())
print(ss2.get_info())


#運行結果爲:
實例一id: 397109139440
實例二id: 397109139440
校名: 古天樂學校 地址: 大涼山 法人表明: 古天樂
校名: 古天樂學校 地址: 大涼山 法人表明: 古天樂

這樣就能夠將這個裝飾器裝飾到任何一個類上,完成單列了設計模式

 

3、__new__方法+靜態字段實現單列模式

 

class Single:
    _single = None
    def __init__(self, value):
        self.v = value
        print(self.v)

    def __new__(cls, *args, **kwargs):
        if Single._single:
            return Single._single
        else:
            Single._single = super(Single, cls).__new__(cls)
            print("只執行一次")
            return Single._single

s2 = Single(2)
s3 = Single(3)
s4 = Single(4)

print(id(s2))
print(id(s3))
print(id(s4))

#輸出結果爲
只執行一次
2
3
4
s2的id爲: 278042421064
s3的id爲: 278042421064
s4的id爲: 278042421064
  • 和類方法相相似,能夠看見,s2/s3/s4 都是同一個id 是同一個實例,儘管實例時傳入的值不同
4、靜態方法+靜態字段實現單列模式

平時咱們在連接數據庫時,一個程序,也是隻須要一個連接就夠了,咱們不但願一個程序產生不少實例去鏈接到數據庫,這樣每一個連接都操做數據庫,不但浪費了內存空間,還可能致使數據修改混亂api

class Sqlpool:
    __single = None #建立一個靜態字段
    def __init__(self):
        #封裝數據庫連接須要的信息
        self.ip = "192.168.1.1"
        self.port = 3306
        self.pwd = "1234567"
        self.username = "xxxxxx"
        
        #連接數據庫
        self.connect = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] #假如建立了9個連接數據庫的線

    @staticmethod 
    def produce():
        if Sqlpool.__single: #判斷靜態字段是否有值
            return Sqlpool.__single #若是有值返回靜態字段的值
        else:
            Sqlpool.__single = Sqlpool() #沒有就實例一個對象給他
            return Sqlpool.__single     #將實例返回

#這樣,不管建立多少個訪問,對象時,都是一個對象,這樣不會佔用內存
conn1 = Sqlpool.produce() #建立一個訪問對象
conn2 = Sqlpool.produce() #建立二個訪問對象

原理都差很少。這個沒有裝飾器好用服務器

5、類/類方法直接實現
class Singleton(object):

    def __init__(self):
        pass

    @classmethod
    def get(cls, *args, **kwargs):
        if not hasattr(Singleton, "_single"):
            Singleton._single = Singleton(*args, **kwargs)
        return Singleton._single

類方法這兒實現單列模式還有優化,就很少說了,是多線程問題。
這兒自己原理和靜態方法差很少。多線程

相關文章
相關標籤/搜索