zoukankan      html  css  js  c++  java
  • 单例设计模式、工厂设计模式和装饰器

    单例模式(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)))"

  • 相关阅读:
    解决ListView异步加载数据之后不能点击的问题
    android点击实现图片放大缩小 java技术博客
    关于 数据文件自增长 的一点理解
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Linux 超级用户的权利
    RAC 实例 迁移到 单实例 使用导出导入
    Shell 基本语法
    Linux 开机引导与关机过程
    RAC 实例不能启动 ORA1589 signalled during ALTER DATABASE OPEN
    Oracle RAC + Data Guard 环境搭建
  • 原文地址:https://www.cnblogs.com/laosun0204/p/9138974.html
Copyright © 2011-2022 走看看