使用python实现单例模式

0 评论
/ /
984 阅读
/
3416 字
11 2019-02
# -*-coding:utf8-*-

# 方法一:可以使用__new__方法
# 在__new__方法中把类实例绑定到类变量_instance上,如果cls._instance为None
# 表示该类还没有实例化过,实例化该类并返回。如果cls_instance不为None表示
# 该类已实例化,直接返回cls_instance
class SingleTon(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = object.__new__(cls, *args, **kwargs)
        return cls._instance


class TestClass(SingleTon):
    a = 1


test1 = TestClass()
test2 = TestClass()
print(test1.a, test2.a)
test1.a = 2
print(test1.a, test2.a)
print(id(test1), id(test2))


# 方法二:使用装饰器,建立过实例的就放到instances里面,下次建立的时候先检查里面有没有
def SingleTon(cls, *args, **kwargs):
    instance = {}

    # print(instance)

    def get_instance(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
            print(instance)
        return instance[cls]

    return get_instance


@SingleTon
class LastClass(object):
    a = 1


test1 = LastClass()
print(test1.a)
test2 = LastClass()
print(test2.a)


# 方法三:使用__metaclass__(元类)关于元类看看这个吧;http://blog.jobbole.com/21351/
class SignalTon(type):
    def __init__(cls, name, bases, dict):
        super(SignalTon, cls).__init__(name, bases, dict)
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(SignalTon, cls).__call__(*args, **kwargs)
        return cls._instance


class TestClass(metaclass=SignalTon):
    pass


test1 = TestClass()
test2 = TestClass()
print(id(test1), id(test2))
test1.a = 2
print(test1.a, test2.a)
print(id(test1) == id(test2))


# 或者使用这种方式
class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Cls4(metaclass=Singleton):
    pass


cls1 = Cls4()
cls2 = Cls4()
print(id(cls1) == id(cls2))


# 方法四:共享属性 所谓单例就是所有的引用(实例,对象)拥有相同的属性和方法,
# 同一个类的实例天生都会有相同的方法,那我们只需要保证同一个类所产生的实例
# 都具有相同的属性。所有实例共享属性最简单直接的方法就是共享__dict__属性指向。
class SingleTon(object):
    _state = {}

    def __new__(cls, *args, **kwargs):
        obj = object.__new__(cls, *args, **kwargs)
        obj.__dict__ = cls._state
        return obj


class TestClass(SingleTon):
    a = 1


test1 = TestClass()
test2 = TestClass()
print(test1.a, test2.a)
test1.a = 2
print(test1.a, test2.a)
print(id(test1), id(test2))


# 方法五:使用同一个模版
# 写在mysingleton.py中
class My_Singleton(object):
    def foo(self):
        pass


my_singleton = My_Singleton()
# 写在要使用这个实例的py文件里面,在不同的引用的地方都引用相同的实例,以此实现单例模式
# from mysingleton import my_singleton
my_singleton.foo()