單例模式:一種軟件設計中經常使用的設計模式,屬於創建型模式中的一種,其目的是確保類只有一個實例。
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,
}