已复制
全屏展示
复制代码

Python单例模式的六种实现


· 2 min read

什么叫做单例模式

单例模式是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,第一次创建实例时是真正的创建了一个实例,而后面创建的实例则是第一次创建的实例的一个引用,是同一个实例。

单例模式多种实现

全局变量方式实现

class Singleton:
    def __init__(self):
        print('Creating.')

settings_instance = None

def Settings():
    global settings_instance
    if settings_instance is None:
        settings_instance = Singleton()
    return settings_instance

s = Settings()
s2 = Settings()
print(s is s2)

元类方式实现

class SingletonMetaclass(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)
        
    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super().__call__(*args, **kwargs)
        return self.__instance
        
class Spam(metaclass=SingletonMetaclass):
    def __init__(self):
        print('Creating Spam')

s = Spam()
s2 = Spam()
print(s is s2)

通过元类方式,定义的元类里面定义两个方法__init____call____init__初始化一个类(元类的一个实例),__call__返回一个类(元类的一个实例),如果这个类已经存在,则直接返回,否则创建一个新的类。

装饰器方式实现

def singleton(cls):
    instance = {}
    def single(*args, **kwargs):
        if cls not in instance:
            instance[cls] = cls(*args, **kwargs)
        return instance[cls]
    return single

@singleton
class Settings:
    def __init__(self):
        print("init instance.")

s1 = Settings()
s2 = Settings()

print(id(s1))
print(id(s2))
print(s1 is s2)

装饰器方式实现是将一个类传递到一个函数里面进行创建,同时判断是否该类已经创建过实例,如果创建过实例,则直接返回创建的实例即可,否则创建新的实例并返回。

类方法方式实现

class Singleton:
    instance = None

    @classmethod
    def singleton(cls, *args, **kwargs):
        if cls.instance is None:
            cls.instance = cls(*args, **kwargs)
        return cls.instance

s = Singleton.singleton()
s2 = Singleton.singleton()

print(id(s))
print(id(s2))
print(s is s2)

也可以使用静态方法创建,静态方法的缺点是一旦类名被改变,则静态方法里面的类名也得改变。

控制类构造函数方式实现

class Singleton:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, "cls_instance"):
            cls.cls_instance = super().__new__(cls, *args, **kwargs)
        return cls.cls_instance

class Settings(Singleton):
    def do_things(self):
        self.name = "yuziyue"

s = Settings()
s.do_things()

s2 = Settings() 
print(s2.name)

print(s is s2)

这种方式实现有一个问题,就在在定义Settings类时,不能写__init__初始化函数,只能是创建实例后,通过实例方法来定义属性。

import 方式实现

# config.py
class Settings():
    redis = "127.0.0.1"
    def __init__():
        print("creating.")

settings = Settings()

# app1.py
from config import settings
print(settings.redis)

# app2.py
from config import settings
print(settings.redis)

Python的模块导入就是一个单例模式,在其他地方导入已经创建好的实例,则该实例不会重新被创建,而是实例本身。

🔗

文章推荐