单例模式

  单例模式是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,当你希望在整个系统中,某个类只出现一个实例时,单例对象就能排上用场

  在python中,我们可以用多种方法来实现单例模式:使用模块、使用__new__、使用装饰器、使用元类(metaclass),共享属性。

使用模块

  其实python的模块就是纯天然的单例模式,因为模块在第一次导入时,会生成.pyc文件,当第二次导入时,就会直接加载.pyc文件,而不会再次执行模块代码。因为,我们只需要把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了。如果我们真的想要一个单例类,可以考虑这样做 

# singleTon.py
class Animal(object):
    def eat(self):
        print('eating...')

a=Animal()

  将上面的代码保存在文件singleTon.py中,然后这样使用:

# my_funcs.py
from singleTon import a
a.eat()

使用__new__

  为了使类只能出现一个实例,我们使用__new__来控制实例的创建过程

# 单例模式基于__new__
class Animal(object):
    _instance=None

    def __new__(cls,*args,**kw):
        if not cls._instance:
            cls._instance=super(Animal,cls).__new__(cls,*args,**kw) #构建一个实例对象

        return cls._instance

# 测试
dog=Animal()
cat=Animal()

print(id(dog))
print(id(cat))

  在上面的代码中,我们将类的实例和一个类变量_instance关联起来,如果cls._instance为None则创建实例,否则直接返回cls._instance

使用装饰器

  装饰器可以动态的修改一个类或函数的功能。这里我们可以使用装饰器来装饰某个类,使其只能生成一个实例

# 单例模式基于装饰器
from functools import wraps

def singleton(cls):
    instances={}

    @wraps(cls)
    def getinstance(*args,**kwargs):
        if cls not in instances:
            instances[cls]=cls(*args,**kwargs)
        return instances[cls]

    return getinstance

@singleton
class Animal(object):
    def eat(self):
        print('eating...')

使用metaclass

  元类可以控制类的创建过程,它主要完成拦截类的创建、修改类的定义,然后返回修改后的类

# 单例模式基于元类

class Singleton(type):
    _instance={}

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

        return cls._instance[cls]

class Myclass(metaclass=Singleton):    
    pass

共享属性

  创建实例时把所有实例的__dict__指向同一个字典,这样它们具有相同的属性和方法

class Singleton(object):

    _state = {}

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

class Myclass(Singleton):
    pass

 

posted @ 2018-06-11 12:58  日新其德止于至善  阅读(149)  评论(0编辑  收藏  举报