Python基础篇:单例模式

Posted 风流 少年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python基础篇:单例模式相关的知识,希望对你有一定的参考价值。

一:单例模式

  • 提供一个静态私有属性:Python在变量名上使用双下划线前缀表示私有属性,例如 __instance, 直接给类.属性赋值就表示是类属性(静态属性)
  • 构造方法私有:Python中__init__方法表示初始化,直接将方法体写成pass,表示这是一个空方法。
  • 提供一个静态方法获取单例对象:一般提供一个函数专门用于获取单例对象,例如get_instance()函数, 根据实现方式的不同,有些实现方式是不需要借助该方法。
  • 单例模式在高并发下可能会创建出多个实例,所以单例模式一般都要使用到锁保证高并发下也只会创建出一个单例。

二:import特性

在类的最底部创建一个当前对象,然后别的地方使用通过导入即可。被导入的代码只会被执行一次。

strtools.py

class StrTools:
    pass


str_tool = StrTools()

demo.py

from strtools import str_tool
st1 = str_tool

demo2.py

from strtools import str_tool
import demo

st2 = str_tool
st3 = str_tool

# 4420422480
print(id(demo.st1))
# 4420422480
print(id(st2))
# 4420422480
print(id(st3))

三:懒汉模式

3.1 类方法方式 get_instance()

只能通过get_instance()静态方法获取对象。

import threading
import time


class Context:
    __instance = None
    __lock = threading.Lock()

    def __init__(self):
        """初始化方法不做任何事情"""
        pass

    @classmethod
    def get_instance(cls, *args, **kwargs):
        if Context.__instance:
            with Context.__lock:
                if Context.__instance:
                    Context.__instance = Context(*args, **kwargs)
        return Context.__instance


inst_set = set()


def test():
    cxt = Context.get_instance()
    inst_set.add(id(cxt))


for i in range(100):
    threading.Thread(target=test).start()

time.sleep(10)
# 1
print(len(inst_set))

3.2 实例化方式 new

在创建对象__new__()时判断是否已经实例化了。

import threading
import time


class Context:
    __instance = None
    __lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if Context.__instance:
            with Context.__lock:
                if Context.__instance:
                    Context.__instance = Context(*args, **kwargs)
        return Context.__instance

    def __init__(self):
        """初始化方法不做任何事情"""
        pass


inst_set = set()
def test():
    cxt = Context()
    inst_set.add(id(cxt))


for i in range(100):
    threading.Thread(target=test).start()

time.sleep(5)
# 1
print(len(inst_set))

3. 装饰器

提供一个字典,key为类,value为实例对象,每次创建对象执行装饰器就会判断字典中有没有该类,如果没有就把当前类作为key实例对象作为value添加到字典中,如果存在则直接从字典中取出即可。

def singleton(cls):
    __instance = 

    def wrapper(*args, **kwargs):
        if cls not in __instance:
            __instance[cls] = cls(*args, **kwargs)
        return __instance[cls]
    return wrapper
@singleton
class Context:
    pass


import time
import threading

inst_set = set()
def test():
    cxt = Context()
    inst_set.add(id(cxt))


for i in range(100):
    threading.Thread(target=test).start()

time.sleep(5)
# 1
print(len(inst_set))

以上是关于Python基础篇:单例模式的主要内容,如果未能解决你的问题,请参考以下文章

Python-单例模式

python全栈开发补充单例模式的四种方式

python中的单例设计模式

python 3 基础之单例模式

python基础之单例模式

单例模式讨论篇:单例模式与垃圾回收