python 单例模式实现

一、重写 new 方法

# -*- coding: utf-8 -*-
# Python 单例模式实现
import pysnooper
import threading


# 方式一, 重写__new__ 方法
class SingletonOne(object):
    _instance = None

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(SingletonOne, cls).__new__(cls, *args, **kwargs)

        return cls._instance

    def __init__(self):
        pass


class SingletonTwo(object):
    _instance = {
    
    }

    # @pysnooper.snoop()
    def __new__(cls, *args, **kwargs):
        key = str(args) + str(kwargs)
        print('key:', key)
        if key not in cls._instance:
            cls._instance[key] = super().__new__(cls)
        return cls._instance[key]

    def __init__(self, name):
        self.name = name


# 多线程
class SingletonLock(object):
    _instance = {
    
    }
    _instance_lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        key = str(args) + str(kwargs)
        if key in cls._instance:
            return cls._instance[key]

        cls._instance_lock.acquire()  # 获取锁对象
        try:
            if key in cls._instance:
                return cls._instance[key]
            cls._instance[key] = super().__new__(cls)
            return cls._instance[key]
        finally:
            cls._instance_lock.release()  # 释放锁对象

    def __init__(self, name):
        self.name = name


def task(name):
    obj = SingletonLock(name)
    print(obj, 'id: ', id(obj))


if __name__ == "__main__":
    s1 = SingletonOne()
    s2 = SingletonOne()
    print('SingletonOne:', id(s1) == id(s2))
    s3 = SingletonTwo('ma')
    s4 = SingletonTwo('ma')
    print('SingletonTwo:', id(s3) == id(s4))

    # 多线程调用
    for i in range(10):
        t = threading.Thread(target=task, args=['ma', ])
        t.start()

    # 正常调用
    c1 = SingletonLock('ma')
    c2 = SingletonLock('ma')
    print('SingletonLock:', id(c1) == id(c2))

二、装饰器方式

# 方式二, 装饰器
def singleton(cls):
    _instance = {
    
    }

    def _singleton(*args, **kwargs):
        key = str(args) + str(kwargs)
        print('key:', key)
        if key not in _instance:
            _instance[key] = cls(*args, **kwargs)
        return _instance[key]

    return _singleton


@singleton
class A(object):

    def __init__(self, x):
        self.x = x


if __name__ == "__main__":
	a1 = A(2)
    a2 = A(3)
    print('A:', id(a1) == id(a2))
    

三、元类的方式

class SingletonType(type):

    _instance = {
    
    }

    def __init__(self, *args, **kwargs):
        super(SingletonType, self).__init__(*args, **kwargs)

    def __call__(cls, *args, **kwargs):  # 这里的cls,即Foo类
        print('cls', cls)
        key = str(args) + str(kwargs)
        if key not in cls._instance:
            cls._instance[key] = cls.__new__(cls, *args, **kwargs)
        return cls._instance[key]

# 线程锁的方式
class SingletonType(type):
    _instance_lock = threading.Lock()

    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, "_instance"):
            with SingletonType._instance_lock:
                if not hasattr(cls, "_instance"):
                    cls._instance = super(SingletonType, cls).__call__(*args, **kwargs)
        return cls._instance


class Foo(metaclass=SingletonType):  # 指定创建Foo的type为SingletonType
    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls)


obj1 = Foo('xx')
obj2 = Foo('xx')
print(id(obj1) == id(obj2))

猜你喜欢

转载自blog.csdn.net/MZP_man/article/details/109227816