单例设计模式、工厂设计模式和装饰器

单例模式(Singleton Pattern)是一种常用的软件设计模式,该模式的主要目的是确保某一个类只有一个实例存在,不管实例化多少次就只有一个实例
单例设计模式的优点是不占内存,每个人都调用一个实例对象

那在python里面怎么怎么实现单例模式呢,单例模式就是只有一个实例,那肯定是指类在实例化的时候,只会实例化一个,就需要用到类里面的一个内置函数__new__,类就是通过这个函数来进行实例化操作的,它在__init__之前先执行
那我们知道类是通过__new__函数来进行实例化的,那就好办了,思路就是先判断一下这个类有没有被实例化过,如果实例化过了,那我们就不要调用继续实例化了,返回原来的那个实例,如果没有被实例化才继续实例化
先写一个普通的类,看一下实例化之后的内存地址,可以看到,正常的一个类,实例化两次,内存地址是不一样的,不是一个对象,如下图:

再写单例模式,再实例化看内存地址是一样的,重写__new__这个方法,如果想实例化必须调用一个父类的__new__(cls)方法,要不然不能实例化,单例模式的写法也很单一,死记硬背就可以了,代码如下:

工厂模式就是类继承,就是流水线模式

本质上由decorator和嵌套的wrapper组成一个共生体,这个共生体我们叫做闭包,闭包满足三个条件
1、函数嵌套函数
2、函数返回函数
3、函数间有参数引用
满足这三个条件的嵌套函数我们称之为闭包,闭包在python中即为修饰器,因此我们可以将代码写成如下形式:

@deco
def f():
print('hello')
time.sleep(1)
print('world')

python装饰器(fuctional decorators)就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能,这个函数的特殊之处在于它的返回值也是一个函数,这个函数是内嵌"原"函数的函数

装饰器的作用:
1、装饰器的本质还是一个函数  
2、在不改变函数调用方式的情况下,对函数进行额外功能的封装(装饰器的作用就是为已经存在的对象添加额外的功能)
3、装饰一个函数,给他加一个其他功能

import time


def deco(f):
def wrapper():
start_time = time.time()
f()
end_time = time.time()
execute_time = round((end_time - start_time) * 1000, 2)
print('运行的时间是 %s ms' % execute_time)
return wrapper


@deco
def f():
print('hello')
time.sleep(1)
print('world')


if __name__ == '__main__':
f()

这里的deco函数就是最原始的装饰器,它的参数是一个函数名,然后返回值也是一个函数名,其中作为参数的这个函数f()就在返回函数wrapper()的内部执行,然后在函数f()前面加上@deco,f()函数就相当于被注入了计时功能,现在只要调用f(),它就已经变身为"新的功能更多"的函数了,不需要重复执行原函数

# 带有固定参数的装饰器
import time


def deco(f):
def wrapper(a, b):
start_time = time.time()
f(a, b)
end_time = time.time()
execute_time = round((end_time - start_time) * 1000, 2)
print('运行的时间是 %s ms' % execute_time)
return wrapper


@deco
def f(a, b):
print('be on')
time.sleep(1)
print('result is %d' % (a + b))


if __name__ == '__main__':
f(3, 4)

# 无固定参数的装饰器
import time


def deco(f):
def wrapper(*args, **kwargs):
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execute_time = round((end_time - start_time) * 1000, 2)
print('运行的时间是 %s ms' % execute_time)
return wrapper


@deco
def f(a, b):
print('be on')
time.sleep(1)
print('result is %d' % (a + b))


@deco
def f2(a, b, c):
print('be on')
time.sleep(1)
print('result is %d' % (a + b + c))


if __name__ == '__main__':
f(3, 4)
f2(3, 4, 5)

# 使用多个装饰器,装饰一个函数
import time


def deco01(f):
def wrapper(*args, **kwargs):
print("this is deco01")
start_time = time.time()
f(*args, **kwargs)
end_time = time.time()
execute_time = round((end_time - start_time) * 1000, 2)
print('运行的时间是 %s ms' % execute_time)
print("deco01 end here")
return wrapper


def deco02(f):
def wrapper(*args, **kwargs):
print("this is deco02")
f(*args, **kwargs)
print("deco02 end here")
return wrapper


@deco01
@deco02
def f(a, b):
print('be on')
print('result is %d' % (a + b))


if __name__ == '__main__':
f(3, 4)

执行结果如下:

装饰器调用顺序:
装饰器是可以叠加使用的,那么使用装饰器以后代码是啥顺序呢?,在这个例子中,"f(3, 4) = deco01(deco02(f(3, 4)))"

原文地址:https://www.cnblogs.com/laosun0204/p/9138974.html