引言
不知道大家有没有这样的疑问?
桌面打开百度网盘登录之后,再次双击图标,返回的还是登录成功后的页面。
微信PC版,登录一个账号之后,再次点击也只是回到了已经登录的账号页面。
......
诸如此类的现象还有很多,那么大家心里有没有疑问呢?为什么我再次点击登录也只是回到了第一次的界面呢?
这就是编程里面的单例思想设计模式的产物。
单例模式
单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)
__new__
__new__() 是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 __init__() 初始化方法被调用。
举例说明一下
很显然,虽然我们实例化了p对象,但是因为由__new__方法存在,所以__init__方法并没有被执行。
那么如何让__init__也被执行呢?
return object.__new__(cls)
#!/usr/bin/env python
class Printer():
def __init__(self, app):
self.app = app
print("-----init------")
def __new__(cls, *args, **kwargs):
#负责执行INIT方法
print("----__new__-----")
#类中的__new__方法被重写后,需要执行父类object中的__new__方法才可以继续执行__init__
return object.__new__(cls)
p = Printer("word")
print(p.app)
执行结果就可以很清楚地看到,__init__被执行了
没有单例思想之前
这样的话就会有三个实例,其实只有一个是可以用的,资源浪费了。
单例模式设计之后
#!/usr/bin/env python
class Printer():
task = []
__instance = None
def __init__(self, app):
self.app = app
def __new__(cls, *args, **kwargs):
if cls.__instance is None:
obj = object.__new__(cls)
print(obj)
cls.__instance = obj
return cls.__instance
def add_task(self, job):
self.task.append(job)
print(f"{self.app}执行任务{job},任务总数是{len(self.task)}")
p1 = Printer("word")
p2 = Printer("excle")
p3 = Printer("pdf")
p1.add_task("word file print")
p2.add_task("excle file print")
p3.add_task("pdf file print")
print(p1, p2, p3)
执行结果:
"C:\Program Files\Python38\python3.exe" D:/python/python_210710/exercise_03/simple_example.py
<__main__.Printer object at 0x0000016A37D86C10>
pdf执行任务word file print,任务总数是1
pdf执行任务excle file print,任务总数是2
pdf执行任务pdf file print,任务总数是3
<__main__.Printer object at 0x0000016A37D86C10> <__main__.Printer object at 0x0000016A37D86C10> <__main__.Printer object at 0x0000016A37D86C10>
可知,此时的实例的内存地址都是C10,而且只保留了最后一个任务的打印操作。后面两次的实例化其实就是执行了__init__函数,并没有生成新的实例,只是对self.app做了修改。
总结
以上就是单例模式通过__new__方法的实现过程。
主要步骤为:
- 通过类变量作为参数,判断实例化准入条件
- 重写__new__方法,返回父类object的实例化对象object.__new__(cls)
- 调用__init__方法实现类的实例化