python中單實例模式實現

單例模式:一種軟件設計中經常使用的設計模式,屬於創建型模式中的一種,其目的是確保類只有一個實例。

1、重寫__new__方法:原理爲通過一個類靜態變量保存對象值,以後每次進行實例化對象時,都使用靜態變量保存的對象值。

2、裝飾器:原理同重新__new__方法一樣

3、元類:原理同上

4、模塊:利用了python加載模塊時,只是第一次運行模塊內容,以後都是直接使用模塊.pyc文件原理

線程安全:多線程中進行單例模式的實現時,因爲多線程是搶佔式,因此需要加鎖才能保證單例模式。

無派生類

singleton.py

# -*- coding: utf-8 -*-
# @Author: kg
# @Date:   2019-01-03 16:06:10
# @Last Modified by:   Administrator
# @Last Modified time: 2019-01-04 16:11:29
# @aim: 實現單例模式
# @env: python3.5

# 無派生類


from unittest import TestCase, main


class newSingleton():
    """重寫__new__方法實現單例模式"""

    _instance = None  # 保存單例實例對象

    def __new__(cls, *args, **kwargs):

        if cls._instance is None:
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance


def getSingleton(cls):
    """裝飾器進行類實例檢查"""
    def check():
        if hasattr(cls, "_instance") is False:
            cls._instance = cls()

        return cls._instance
    return check


@getSingleton
class deSingleton():
    """裝飾器實現單例模式"""
    pass


class metaSingleton(type):
    """元類方式實現單例模式"""

    _instance = None

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super().__call__(*args, **kwargs)

        return cls._instance


class mySingleton(metaclass=metaSingleton):
    """元類直接實例化比較複雜,所以使用額外類完成單實例對象"""
    pass


class myTest(TestCase):
    """單元測試"""

    def testNewSingleton(self):
        a = newSingleton()
        b = newSingleton()
        c = newSingleton()

        print("test in testNewSingleton ")
        print("a = {}, b = {}, c = {}".format(a, b, c))
        print("a = b = c is {} \n".format(id(a) == id(b) == id(c)))

    def testdeSingleton(self):
        a = deSingleton()
        b = deSingleton()
        c = deSingleton()

        print("test in testdeSingleton ")
        print("a = {}, b = {}, c = {}".format(a, b, c))
        print("a = b = c is {} \n".format(id(a) == id(b) == id(c)))

    def testmySingleton(self):
        a = mySingleton()
        b = mySingleton()
        c = mySingleton()

        print("test in testmySingleton ")
        print("a = {}, b = {}, c = {}".format(a, b, c))
        print("a = b = c is {} \n".format(id(a) == id(b) == id(c)))

    def testModelFirst(self):
        import singletonmodel
        myTest.first = singletonmodel.model_obj
        print("first self is ", self, id(self))

    def testModelSecond(self):
        import singletonmodel
        myTest.second = singletonmodel.model_obj

        print("second self is ", self, id(self))
        print("test in testModelSingleton ")
        print("first {}, second {}".format(myTest.first, myTest.second))
        print("first == second is ", id(myTest.first) == id(myTest.second))


if __name__ == "__main__":
    main()

singletonmodel.py

# -*- coding: utf-8 -*-
# @Author: kg
# @Date:   2019-01-02 17:04:42
# @Last Modified by:   Administrator
# @Last Modified time: 2019-01-04 16:00:07
# @aim: 模塊方式實現單例模式
# @env: python3.5


class modelSingleton():
    """模塊方式實現單例模式"""


model_obj = modelSingleton()

 

派生類:爲了實現子類安全(即繼承了單例模式類的子類也是單例模式),實現原理爲將保存實例化對象變量設置爲字典即可,key爲類名稱,value爲類對象值。原因是:由於類名稱空間原因,不同的實例順序會造成某些子類不是單例模式。

# -*- coding: utf-8 -*-
# @Author: kg
# @Date:   2019-01-03 16:06:10
# @Last Modified by:   Administrator
# @Last Modified time: 2019-01-04 17:11:06
# @aim: 實現單例模式
# @env: python3.5

# 派生類


def test_subsingleton():

    class newSingleton():
        """
        採用不可變類型保存對象值時,子類會出現不安全情況,嚴重依賴於實例化對象的順序
        """

        _instance = None  # 採用不可變類型保存對象值時,子類不安全

        def __new__(cls, *args, **kwargs):

            if cls._instance is None:
                cls._instance = super().__new__(cls, *args, **kwargs)
            return cls._instance

    class firstChild(newSingleton):
        pass

    class secondChild(newSingleton):
        pass

    def testfitst():
        base = newSingleton()
        first = firstChild()
        second = secondChild()
        print("test in testfitst ")
        display(base, first, second)

    def testsecond():
        first = firstChild()
        base = newSingleton()
        second = secondChild()

        print("test in testsecond ")
        display(base, first, second)

    def testthird():
        first = firstChild()
        second = secondChild()
        base = newSingleton()

        print("test in testthird ")
        display(base, first, second)

    def display(base, first, second):

        print(
            "base= {}, first = {}, second = {}".format(base, first, second))
        print(
            "base= first = second is ", id(base) == id(first) == id(second))

    # testfitst()
    testsecond()
    # testthird()


def test_safe_subsingleton():

    class safeNewSingleton():
        """
        採用可變類型保存對象值時,子類安全,與實例化時的順序無關,同時也是單例模式
        """

        _instance = {}  # 根據類名保存對象值

        def __new__(cls, *args, **kwargs):

            if cls not in cls._instance:
                cls._instance[cls] = super().__new__(cls, *args, **kwargs)
            return cls._instance[cls]

    class firstChild(safeNewSingleton):
        pass

    class secondChild(safeNewSingleton):
        pass

    def testfitst():
        base = safeNewSingleton()
        first = firstChild()
        second = secondChild()
        print("test in testfitst ")
        display(base, first, second)

    def testsecond():
        first = firstChild()
        base = safeNewSingleton()
        second = secondChild()

        print("test in testsecond ")
        display(base, first, second)

    def testthird():
        first = firstChild()
        second = secondChild()
        base = safeNewSingleton()

        print("test in testthird ")
        display(base, first, second)

    def display(base, first, second):

        print(
            "base= {}, first = {}, second = {}".format(base, first, second))
        print(
            "base= first = second is ", id(base) == id(first) == id(second))

    # testfitst()
    testsecond()
    # testthird()


def main():
    print("\n run fo test_subsingleton")
    test_subsingleton()
    print("\n run fo test_safe_subsingleton")
    test_safe_subsingleton()


if __name__ == "__main__":
    main()

test_subsingleton中子類不安全原因爲:

test_subsingleton中testsecond函數執行過程:
first = firstChild()執行過程:
    運行前,firstChild類名稱空間中只有父類指針(newSingleton)
    運行時,cls._instance因爲firstChild類空間中沒有找到,向上查找(即newSingleton),
    這時候newSingleton._instance值爲None,滿足cls._instance is None條件,
    執行super().__new__(cls, *args, **kwargs),同時將實例化後的對象值賦值給了
    firstChild._instance,這時候firstChild類名稱空間中增加了一個新屬性_instance。
    注意:這時候是在firstChild類名稱空間中增加了_instance屬性,而不是將newSingleton._instance值
         設置爲實例化後的對象值。
    運行結束後,firstChild類名稱空間中增加了一個新屬性_instance


base = newSingleton()執行過程:
    運行前,newSingleton類名稱空間中有_instance和父類指針(object, python3隱式繼承object)
    運行時,cls._instance(newSingleton._instance)值爲None,滿足cls._instance is None條件,
    執行super().__new__(cls, *args, **kwargs),同時將newSingleton._instance值設置爲實例化後的對象值。
    運行結束後,newSingleton._instance爲非None


second = secondChild()執行過程:
    運行前,secondChild類名稱空間中只有父類指針(newSingleton)
    運行時,cls._instance因爲secondChild類空間中沒有找到,向上查找(即newSingleton),
    這時候newSingleton._instance值爲非None,不滿足cls._instance is None條件,返回
    cls._instance(即newSingleton._instance值)

test_safe_subsingleton中子類安全原因爲:

test_safe_subsingleton中testsecond函數執行過程:
first = firstChild()執行過程:
    運行前,firstChild類名稱空間中只有父類指針(newSingleton)
    運行時,cls._instance,因爲firstChild類空間中沒有找到,向上查找(即newSingleton),
    這時候newSingleton._instance值爲空字典,滿足
    cls(firstChild) not in cls._instance(newSingleton._instance)條件,
    執行super().__new__(cls, *args, **kwargs),同時將實例化後的對象值賦值給
    cls._instance[cls](即newSingleton._instance["firstChild"] = 對象值)
    運行結束後,newSingleton._instance字典值爲{"firstChild": firstChild_obj}


base = newSingleton()執行過程:
    運行前,newSingleton類名稱空間中有_instance和父類指針(object, python3隱式繼承object)
    運行時,cls._instance(newSingleton._instance)值爲{"firstChild": firstChild_obj},
    滿足cls(newSingleton) not in cls._instance(newSingleton._instance)條件,執行
    super().__new__(cls, *args, **kwargs),同時將實例化後的對象值賦值給
    cls._instance[cls](即newSingleton._instance["newSingleton"] = 對象值)
    運行結束後,newSingleton._instance字典值爲 {
    "firstChild": firstChild_obj, 
    "newSingleton": newSingleton_obj}


second = secondChild()執行過程:
    運行前,secondChild類名稱空間中只有父類指針(newSingleton)
    運行時,cls._instance,因爲secondChild類空間中沒有找到,向上查找(即newSingleton),
    這時候newSingleton._instance值爲{"firstChild": firstChild_obj, "newSingleton": newSingleton_obj},
    滿足cls(secondChild) not in cls._instance(newSingleton._instance)條件,執行
    super().__new__(cls, *args, **kwargs),同時將實例化後的對象值賦值給
    cls._instance[cls](即newSingleton._instance["secondChild"] = 對象值)
    運行結束後,newSingleton._instance字典值爲 {
    "firstChild": firstChild_obj, 
    "newSingleton": newSingleton_obj, 
    "secondChild": secondChild_obj,
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章