单例模式业务场景及实现的几种方式

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)

 

posted @ 2018-09-07 19:54  -Learning-  阅读(776)  评论(0编辑  收藏  举报