美文网首页
实现单例模式的方式

实现单例模式的方式

作者: BigBigTang | 来源:发表于2019-03-06 22:34 被阅读0次

在使用logging这个模块进行单一log文件记录的时候碰到了log重复的问题,原因在于反复的调用log对象可能会加入重复的file或console handler,导致一次调用多次打印的问题
解决方法:
1.可以在每次用完logger对象后删除handler
2.不同的地方创建logger时,使用不同的name
3.使用单例
本文是对单例实现的几种方法作简单分析

1.通过重载__new__方法

class MyLogger(object):

    _instance = None

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

在创建类的时候重写__new__方法
首先加一个类变量_instance = None
在__new__方法中做判断,如果_instance为初始的None,就通过super继承object的__new__方法来生成实例对象返回给_instance,这样从第二次开始实例化类,_instance对象都不再是None,会直接return cls._instance返回第一次那个实例化的对象。

2.通过装饰器

from functools import wraps

def singleton(cls):
    _instance = {}
    @wraps(cls)
    def wrapper(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]
    return wrapper

@singleton
class my_singleton(object):
    pass

a = my_singleton()
b = my_singleton()
print(id(a))
print(id(b))

通过装饰器实现的话原理类似,def singleton(cls):中的cls是传入的类实例
在装饰器函数中写一个_instance字典初始为空,如果cls这个实例对象不在_instance中就把这个实例对象添加到字典中,然后通过字典返回这个实例对象。从第二次开始创建实例,都是直接返回_instance字典中的第一次存入的实例对象。

需要注意
由于使用装饰器后实际上是返回了一个新的函数,一些原本的信息会丢失,比如函数名,在这个例子中我原本的类名是my_singleton,使用装饰器后类名就变成装饰器singleton的名字。
所以这里还引入了functools中的wraps装饰器,这个装饰器实现的作用是将原本的信息保留,注意使用@wraps的时候需要把参数cls传递,否则内层的wrapper无法获取到cls

3.使用元类 metaclass singleton

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance
class MyClass(object, metaclass=Singleton):
    pass

class1 = MyClass()
class2 = MyClass()
print(id(class1))
print(id(class2))

解析:对于一个类的实例化,如上例中的
class1 = MyClass()
通过类MyClass()实例化了一个对象class1,()是调用,MyClass()实际上执行的是MyClass类的__call__方法,所以从元类的角度实现单例的话,可以通过限制类的__call__。
每次实例化对象的时候调用的都是同一个__call__,得到的自然是同一个对象。
另外,元类Singleton必须继承type,python中类默认通过type来创建,要写一个元类来创建别的类,也就必须要继承type。

相关文章

  • 单例模式的常用实现方式

    单例模式属于最常用的设计模式,Java中有很多实现单例模式的方式,各有其优缺点 实现方式对比 单例实现方式线程安全...

  • 设计模式--单例模式

    单例模式概述 单例模式实现方式 为什么要使用单例模式 单例模式实现方式 饿汉式 类加载后就会将对象加载到内存中,保...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • Python经典面试题21道

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python最经典面试题21道,必看!

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python 经典面试题

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python 经典面试题

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • 单例模式(Singleton)- 通俗易懂的设计模式解析

    单例模式的实现方式单例模式的实现方式有多种,根据需求场景,可分为2大类、6种实现方式。具体如下: a. 初始化单例...

  • 2018-06-19 Python中的单例模式的几种实现方式的及

    转载自: Python中的单例模式的几种实现方式的及优化 单例模式 单例模式(Singleton Pattern)...

  • 常见的设计模式

    创建型模式 结构型模式 行为模式 单例模式 单例模式的优点 常见的五种单例模式实现方式 单例带来的问题 如何选择 ...

网友评论

      本文标题:实现单例模式的方式

      本文链接:https://www.haomeiwen.com/subject/gbrfpqtx.html