基本介绍
单例模式(Singleton Pattern)即一个类只能拥有一个实例对象,实例化多次的结果都会指向同一个对象。
特点:全局唯一,允许更改
该模式属于创建型模式,同时也是创建型模式中应用最为广泛的一种。
案例图示
从配置文件中读取配置来进行实例化,在配置相同的情况下,就没必要重复产生对象浪费内存了,只有在配置不同的情况下才会生成新的实例。
文件内容如下:
# settings.py文件内容如下
HOST = "localhost"
PORT = 3306
案例图示:
优缺点
优点:
- 避免对资源的多重占用,如写入文件操作
- 节省内存
- 防止命名空间被污染
缺点:
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化
代码实现
Python实现单例模式手段较多,这里例举5种比较常见的。
继承实现
基础代码如下:
class Singleton:
def __new__(cls, *args, **kwargs) -> object:
"""
cls : class Category
"""
if not hasattr(cls, "ins"):
singletonInsObject = super(__class__, cls).__new__(cls, *args, **kwargs)
setattr(cls, "ins", singletonInsObject)
return getattr(cls, "ins")
class Category(Singleton):
pass
if __name__ == "__main__":
ins = Category()
print(id(ins))
ins = Category()
print(id(ins))
元类实现
基础代码如下:
class MetaClass(type):
def __call__(self, *args, **kwargs):
"""
self : class Category
"""
if not hasattr(self, "ins"):
singletonInsObject = super(__class__, self).__call__(*args, **kwargs)
setattr(self, "ins", singletonInsObject)
return getattr(self, "ins")
class Category(object, metaclass=MetaClass):
pass
if __name__ == "__main__":
ins = Category()
print(id(ins))
ins = Category()
print(id(ins))
装饰器实现
基础代码如下:
def warpper(clsObject):
def inner(*args, **kwargs):
if not hasattr(clsObject, "ins"):
singletonInsObject = clsObject(*args, **kwargs)
setattr(clsObject, "ins", singletonInsObject)
return getattr(clsObject, "ins")
return inner
@warpper
class Category:
pass
if __name__ == "__main__":
ins = Category()
print(id(ins))
ins = Category()
print(id(ins))
模块实现
基础代码如下:
- foo.py --> ins = Category()
- bar.py --> from foo import ins
@classmethod实现
基础代码如下:
class Category:
@classmethod
def getSingletonInstanceObject(cls, *args, **kwargs):
if not hasattr(cls, "ins"):
singletonInsObject = cls(*args, **kwargs)
setattr(cls, "ins", singletonInsObject)
return getattr(cls, "ins")
if __name__ == "__main__":
ins = Category.getSingletonInstanceObject()
print(id(ins))
ins = Category.getSingletonInstanceObject()
print(id(ins))
案例实现
案例实现采用元类实现、装饰器实现以及@classmethod实现.
1)元类实现:
import settings
class MetaClass(type):
"""
self : class MySQL
"""
def __call__(self, *args, **kwargs):
常规实例化
if args or kwargs:
insObject = object.__new__(self)
self.__init__(insObject, *args, **kwargs)
return insObject
采用默认配置实例化,生成单例对象
if not hasattr(self, "ins"):
singletonInsObject = object.__new__(self)
self.__init__(singletonInsObject, settings.HOST, settings.PORT)
setattr(self, "ins", singletonInsObject)
return getattr(self, "ins")
class MySQL(object, metaclass=MetaClass):
def __init__(self, host, port) -> None:
self.host = host
self.port = port
if __name__ == "__main__":
ins1 = MySQL("192.168.0.1", 3306)
ins2 = MySQL("192.168.0.1", 3307)
print(ins1 is ins2)
ins3 = MySQL()
ins4 = MySQL()
print(ins3 is ins4)
# False
# True
2)装饰器实现:
import settings
def warpper(cls):
singletonInsObject = cls(settings.HOST, settings.PORT)
def inner(*args, **kwargs):
常规实例化
if args or kwargs:
insObject = cls(*args, **kwargs)
return insObject
采用默认配置实例化,生成单例对象
return singletonInsObject
return inner
@warpper
class MySQL:
def __init__(self, host, port) -> None:
self.host = host
self.port = port
if __name__ == "__main__":
ins1 = MySQL("192.168.0.1", 3306)
ins2 = MySQL("192.168.0.1", 3307)
print(ins1 is ins2)
ins3 = MySQL()
ins4 = MySQL()
print(ins3 is ins4)
# False
# True
3)@classmethod实现:
import settings
class MySQL:
singletonInsObject = None
常规实例化
def __init__(self, host, port) -> None:
self.host = host
self.port = port
采用默认配置实例化,生成单例对象
@classmethod
def getSingletonInstanceObject(cls):
if not cls.singletonInsObject:
cls.singletonInsObject = cls(settings.HOST, settings.PORT)
return cls.singletonInsObject
if __name__ == "__main__":
ins1 = MySQL("192.168.0.1", 3306)
ins2 = MySQL("192.168.0.1", 3307)
print(ins1 is ins2)
ins3 = MySQL.getSingletonInstanceObject()
ins4 = MySQL.getSingletonInstanceObject()
print(ins3 is ins4)
# False
# True