风清扬

导航

Python 设计模式之路(五)——单例模式

本节内容

  1. 什么是单例模式
  2. 作用
  3. Python实现
  4. 多线程的思考
  5. 弊端

一、什么是单例模式

类仅产生一个实例,且提供了这个实例的全局访问,这种模式就称之为单例模式

二、作用

  • 确保类的实例被创建一个
  • 为对象提供了一个全局访问点,即对象可被访问
  • 控制共享资源的并行访问,即:共享资源指一个实例,同时访问指多个实例引用

三、Python实现

1.__new__ 方法

class Signleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            cls._instance = super().__new__(cls)
        return cls._instance

if __name__ == '__main__':
    s = Signleton()
    s1 = Signleton()
    print(s,s1)

2.类方法

class Singleton:
    _instance = None
    def __init__(self):
        pass
    @classmethod
    def get_instance(cls):
        if not cls._instance:
            cls._instance = Singleton
        return cls._instance

3.静态方法

class A:
    pass
class B:
    pass

class InstanceFactory:
    _instances = {}
    @staticmethod
    def get_instance(cls):
        if cls not in InstanceFactory._instances:
            InstanceFactory._instances[cls] = cls()
        return InstanceFactory._instances[cls]

a1 = InstanceFactory.get_instance(A)
a2 = InstanceFactory.get_instance(A)
b1 = InstanceFactory.get_instance(B)
b2 = InstanceFactory.get_instance(B)

print(a1,a2)
print(b1,b2)

4.元类+__call__方法

# 5.元类控制
# 思路: 元类控制类对象的创建,__call__可以控制对象调用, 元类+__call__可以实现单例
class MetaType(type):
    _instances = {}
    #拦截对象的__new__,__init__方法
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(MetaType, cls).__call__(*args, **kwargs) #type.__call__

        return cls._instances[cls]


class A(metaclass=MetaType):
    pass

四、多线程的思考

# 补充:多线程版本
from threading import Lock
class Singleton(object):
    singleton_lock = Lock()

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls,'_instance'):
            with Singleton.singleton_lock:
                if hasattr(cls,'_instance'):
                    cls._instance = super().__new__(cls)
        return cls._instance

五、弊端

  • 一个实例,有多个引用=> 实例的状态难以把控
  • 提供全局访问入口=>其他类乱引用,紧耦合

  

 

  

 

 

posted on 2019-01-28 11:25  卜戈的博客  阅读(232)  评论(0编辑  收藏  举报