【Python】单例模式
一、引言
单例模式是比较简单的设计模式之一,其涉及单一的类,该类负责创建自己,并确保只有单个的对象被创建,给外部提供其唯一的对象访问方式,并且外部不需要显示的实例化该类。今天我们就来介绍Python中编写单例类的一些方法。
二、常规形式
首先是最常见的编写一个单例类的方式,具体代码如下,通过一个类的静态方法来获取该类的唯一对象(如果没有则创建)。当然我这里没有考虑线程同步问题,如果有必要可以加入线程锁。
class Singleton: _instance = None @staticmethod def get_instance(): if Singleton._instance is None: Singleton._instance = Singleton() return Singleton._instance def __init__(self): pass def method1(self): pass def method2(self): pass #### 外部调用方式 Singleton.get_instance().method1() # 调用方法1 Singleton.get_instance().method2() # 调用方法2
三、可重用继承形式
在C++中我们可以通过模板类实现单例,其他需要变成单例类的类只需要继承此模板即可。Python中也可以做到写一个可继承的单例类,其他需要变成单例的类继承此类。具体代码代码如下:
class Singleton(object): """ 可继承单例类 """ def __init__(self, *args, **kwargs): pass def __new__(cls, *args, **kwargs): if not hasattr(cls, "instance_dict"): Singleton.instance_dict = {} class_name = cls.__name__ if class_name not in Singleton.instance_dict: _instance = super().__new__(cls) Singleton.instance_dict[class_name] = _instance return Singleton.instance_dict[class_name]
只需要将设计为单例的类继承自上面的Singleton类即可,但在访问其方法的时候会有一些不同,类似每次都调用类的初始化,但初始化返回的都是同一个已生成的对象实例。具体代码如下:
class TestA(Singleton): def method1(self): pass def method2(self): pass ### 外部调用方式 TestA().method1() TestA().method2()
三、采用装饰器形式
上面的方法是采用继承的方式实现,也可以采用装饰器的方式。定义一个装饰器方法然后在需要定义为单例的类上加上装饰器代码即可,代码如下:
def singleton(cls, *args, **kwargs): instance = {} def get_instance(*args, **kwargs): if cls not in instance: _instance = object.__new__(cls) _instance.__init__(*args, **kwargs) instance[cls] = _instance return instance[cls] return get_instance
@singleton class TestA(object): def method1(self): pass def method2(self): pass ### 外部调用方式 TestA().method1() TestA().method2()
四、强迫症的实现形式
为什么会出现这种实现形式,主要是我不想每次都写ClassA.get_instance().method(), 也不想采用ClassA().method()这种看上去每次都是在创建对象的方式。我希望的是可以直接ClassA.method() 像访问静态方法一样的方式。最后还真的让我找到了实现方法,也是采用装饰器形式。具体代码如下:
class ClassMethod: def __init__(self,func): self.func = func def __get__(self, instance, owner): class_name = owner.__name__ if not hasattr(owner, "__instance_dict"): setattr(owner, "__instance_dict", {}) instance_dict = getattr(owner, "__instance_dict") if class_name not in instance_dict: instance_dict[class_name] = owner() def deco(*args,**kwargs): _instance = instance_dict[class_name] self.func(_instance,*args) return deco
class TestA: @ClassMethod def method1(self): pass @ClassMethod def method2(self): pass ### 外部调用方式 TestA.method1() TestA.method2()
实现单例模式的方法就介绍这几个了,针对方法二、方法二是网上找到的例子,但在实际使用中这两种方法都存在一些问题,具体是什么问题就靠大家在实践中去发现啦。最后这种方法麻烦就在每个方法上都有加,大家如果还有更好的方法,欢迎留言发给我哟。
欢迎微信搜索"游戏测试开发"关注一起沟通交流。