单例模式

2018-02-12  本文已影响7人  马小跳_

理解单例模式

单例模式提供了这样一个机制,即确保类有且只有一个特定类型的对象,并提供全局访问点。因此,单例模式通常用于下列情形,例如日志记录或数据库操作、打印机后台处理程序,以及其他程序 — 该程序运行过程中只能生成一个实例,以避免对同一资源产生相互冲突的请求。

例如,我们可能希望使用一个数据库对象对数据库进行操作,以维护数据的一致性;或者希望使用一个日志类的对象,将多项服务的日志信息按照顺序转储到一个特定的日志文件中。

简言之,单例设计模式的意图如下所示:

Python实现的单例模式

普通青年版

通过重写类的__new__方法来控制对象的创建。

class Singleton(object):
    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Singleton, cls).__new__(cls)
        return cls.instance

s = Singleton()
print(s)  # <__main__.Singleton object at 0x0000023C753BB198>
s1 = Singleton()
print(s1)  # <__main__.Singleton object at 0x0000023C753BB198>

模块级别的单例模式

默认情况下,所有的模块都是单例,这是由 Python 的导入行为所决定的。

Python 通过下列方式来工作:

单态模式

GoF(the Gang of Four,GoF)的单例设计模式是指,一个类有且只有一个对象。然而,根据 Alex Martelli 的说法,通常程序员需要的是让实例共享相同的状态。他建议开发人员应该关注状态和行为,而不是同一性。由于该概念基于所有对象共享相同状态,因此它也被称为 Monostate(单态)模式。

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state
        pass

b = Borg()
b1 = Borg()
b.name = 'mxt'
print(b, b.__dict__)  # <__main__.Borg object at 0x00000203F1061588> {'name': 'mxt'}
print(b1, b1.__dict__)  # <__main__.Borg object at 0x00000203F10615F8> {'name': 'mxt'}
b1.age = 18
print(b.__dict__)  # {'name': 'mxt', 'age': 18}
print(b1.__dict__)  # {'name': 'mxt', 'age': 18}

上面的代码中,我们将类变量__shared_state赋给了特殊变量__dict__,用来存储一个类所有对象的状态。

两个实例“b”和“b1”是两个不同的对象,这一点与单例模式大为不同,后者只能生成一个对象。然而,对象的状态,
b.__dict__b.__dict__却是相同的。

也可以通过__new__实现单态

class Borg(object):
    _shared_state = {}
    def __new__(cls, *args, **kwargs):
        obj = super(Borg, cls).__new__(cls, *args, **kwargs)
        obj.__dict__ = cls._shared_state
        return obj

通过元类实现单例

# 类的两种创建方法
class A(object):
    name = 'mxt'

B = type('B', (object,), {'name': 'mxt'})

Python中可以通过A=type(name,bases,dict)创建一个类,这种方式有三个参数:

现在,如果一个类有一个预定义的元类,那么 Python 就会通过A=MetaCls(name,bases,dict)来创建类。

元类实现的单例:

class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

# 只要指定SingletonMeta元类,创建的这个类就是单例的
class Logger(metaclass=SingletonMeta):
    pass

logger1 = Logger()
logger2 = Logger()
print(logger1)  # <__main__.Logger object at 0x000001E2CE1C1630>
print(logger2)  # <__main__.Logger object at 0x000001E2CE1C1630>

单例模式的缺点

虽然单例模式在许多情况下效果很好,但这种模式仍然存在一些缺陷。由于单例具有全局访问权限,因此可能会出现以下问题:

上一篇下一篇

猜你喜欢

热点阅读