單例模式業務場景及實現的幾種方式

1.業務場景

  windows的回收站其實就是一個單例,你雙擊第二次並不會在出現一個出現窗口,對象只會創建一次

  第三方sdk做接口發送短信驗證碼,如果有幾十萬個用戶同時發送短信,只需調用對象的方法即可

  我們一般在調用數據庫的時候也採用單例模式來實現的,這樣避免了內存空間不必要的佔用和浪費

2.文件導入的形式

  模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。

  這個其實在django中的admin組件用到過,自己編寫相關組件時候,相當的有用

s1.py

class Foo(object):
    def test(self):
        print("123")

v = Foo()
#v是Foo的實例

s2.py
from s1 import v as v1  # 第一次導入,實例化並放進內存

s3.py from s1 import v as v2  # 第二次導入直接從內存中獲取

2.基於類實現

2.1 基於__new__方法實現

常見模式1:

class B:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls)
        return cls.__instance
    def __init__(self,name,age):
        self.name = name
        self.age = age
     
a = B('alex',80)
b = B('egon',20)
print(a) 
print(b)
print(a.name)
print(b.name)
 
# <__main__.B object at 0x04F1D330>    # 結果相同
# <__main__.B object at 0x04F1D330>  
# egon
# egon

常見模式2:

class A:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'instance'):
            # 每次實例化,都返回這同一個對象
            cls.instance = super().__new__(cls)
        return cls.instance
obj1 = A()
obj2 = A()
obj1.attr = 'value'
print(obj1.attr)
print(obj2.attr)
 
# value
# value

2.2 與線程相關

不支持多線程:

class Singleton(object):

    def __init__(self):
        import time
        time.sleep(1)

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

import threading

def task(arg):
    obj = Singleton.instance()
    print(obj)

for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()

 支持多線程:

import time
import threading
class Singleton(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        time.sleep(1)

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Singleton, "_instance"):
            with Singleton._instance_lock:   #爲了保證線程安全在內部加鎖
                if not hasattr(Singleton, "_instance"):
                    Singleton._instance = Singleton(*args, **kwargs)
        return Singleton._instance


def task(arg):
    obj = Singleton.instance()
    print(obj)
for i in range(10):
    t = threading.Thread(target=task,args=[i,])
    t.start()
time.sleep(20)
obj = Singleton.instance()
print(obj)

# 使用先說明,以後用單例模式,obj = Singleton.instance()
# 示例:
# obj1 = Singleton.instance()
# obj2 = Singleton.instance()
# print(obj1,obj2)
# 錯誤示例
# obj1 = Singleton()
# obj2 = Singleton()
# print(obj1,obj2)

3.通過裝飾器實現

def wrapper(cls):
    instance = {}
    def inner(*args,**kwargs):
        if cls not in  instance:
            instance[cls] = cls(*args,**kwargs)
        return instance[cls]
    return inner

@wrapper
class Singleton(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age

obj1 = Singleton('尼古拉斯',99)
obj2 = Singleton('藍恩',19)
print(obj1)
print(obj2)

 

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