OpenStack中的设计模式1:单例模式

设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。从而可以通过使用设计模式让代码更容易被别人理解,同时有保证了代码的可靠性。

单例模式(Singleton Pattern)最初的定义出现于《设计模式》(艾迪生维斯理, 1994):“保证一个类仅有一个实例,并提供一个访问它的全局访问点。” 对于面向对象编程,有一些对象其实只需要一个,比如:线程池、缓存、配置文件和注册表的对象、日志对象等。事实上,这些对象只能有一个实例。单例模式与全局变量一样方便,又没有全局变量的缺点。

如果程序中引入了多线程,那么需要对Singleton Pattern进行优化,一般 对线程敏感的资源(临界资源)进行加锁。

要点:

  • 单例模式确保程序中一个类最多只有一个实例;
  • 单例模式也提供这个实例的全局点;
  • 确定在性能和资源上的限制,然后小心地选择适当的方案来实现单例,以解决多线程的问题;
  • 初始化类时,实例被创建,这种称为“饿汉”单例模式;
  • 当需要获取实例时,实例才被创建,这种称为“懒汉”单例模式。
#Excerpted:oslo_service/service.py
class Singleton(type):
    _instances = {}
    _semaphores = lockutils.Semaphores()

    def __call__(cls, *args, **kwargs):#<--cls:str"OneClass"
        with lockutils.lock('singleton_lock', 
			semaphores=cls._semaphores):
            if cls not in cls._instances:
                cls._instances[cls] = 
			super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]

通过修饰(参考廖雪峰的官方网站)的方式,class Singleton作为修饰函数six.add_metaclass的参数传入,被修饰的class OneClass实例化的对象ab是相同的。

@six.add_metaclass(Singleton)
class OneClass():
	pass

a = OneClass()
b = OneClass()
print(a==b)
#True

#Excerpted:six.py
def add_metaclass(metaclass):#<--metaclass:Singleton
    """Class decorator for creating a class with a metaclass."""
    def wrapper(cls):#<--cls:OneClass
        orig_vars = cls.__dict__.copy()
        slots = orig_vars.get('__slots__')
        if slots is not None:
            if isinstance(slots, str):
                slots = [slots]
            for slots_var in slots:
                orig_vars.pop(slots_var)
        orig_vars.pop('__dict__', None)
        orig_vars.pop('__weakref__', None)
        return metaclass(cls.__name__, cls.__bases__, orig_vars)
		#<--Singleton(OneClass,(),orig_vars)
    return wrapper

Singleton中定义的类属性_instance,类变量对所有对象唯一,即所有实例都有唯一的属性_instance。


参考

  1. Wiki百科:Singleton Pattern
  2. metaclass
  3. Python官网