python设计模式6装饰器模式

Posted Htojk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python设计模式6装饰器模式相关的知识,希望对你有一定的参考价值。

哲学思想

装饰器模式是一种结构型设计模式,其哲学思想是通过组合和装饰对象来扩展其功能,而不需要修改其底层代码或继承新的类。它遵循了"开放封闭原则",即对扩展开放,对修改关闭。

该模式的核心概念是将一个类包装在另一个类中,以便为原始对象添加新的行为或责任,同时保持其原始接口不变。这种包装方式可以在运行时动态添加或删除功能,从而使应用程序更加灵活和可扩展。

从哲学的角度来看,装饰器模式反映了一种实用主义的思想,即在不改变对象本质的前提下,尽可能地扩展其功能。它强调了在软件设计中遵循最小化修改和尽可能复用的原则。这种设计方式有助于提高代码的可维护性和可重用性,并促进了面向对象编程的良好实践。

简介

装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许将行为动态添加到一个对象中,而不必改变该对象的类。这种模式利用了组合的方式,以在运行时动态地添加功能,同时避免了静态类继承的缺点。

装饰器模式的基本思想是:将一个对象“包装”在另一个对象中,从而实现增强原有对象的功能,而不改变原有对象的结构。这种方式可以让我们通过添加新的装饰器来动态地改变对象的行为,而无需对其进行修改。

装饰器模式的实现通常涉及创建一个抽象的装饰器类和一个具体的装饰器类,这个具体的装饰器类可以添加额外的行为或修改对象的行为。同时,还需要创建一个具体的组件类,它是被装饰的对象。最终,装饰器模式将组件类和装饰器类组合起来,以实现动态添加功能的目的。

装饰器模式常常应用于需要动态添加功能或修改对象行为的场景,例如在不改变现有代码的情况下为一个类添加新的功能,或在运行时添加日志、缓存等功能。

优点:

  1. 增强对象功能:装饰器模式可以增强一个对象的功能,而不需要修改原始对象的代码。通过添加不同的装饰器,可以在运行时为对象增加不同的功能,从而满足不同的需求。

  2. 可扩展性:装饰器模式非常灵活,允许在运行时动态地添加或删除功能,因此非常适合应对需求的变化。

  3. 组合性:装饰器模式允许将多个装饰器组合在一起使用,从而实现更复杂的功能。

  4. 单一职责原则:装饰器模式遵循单一职责原则,每个装饰器只关注一个特定的功能,使得代码更加清晰简洁。

  5. 开闭原则:装饰器模式遵循开闭原则,可以在不修改原始对象的情况下扩展其功能,从而保证了系统的可维护性和可扩展性。

缺点

  1. 增加了代码复杂性:使用装饰器模式会增加代码的复杂度,因为需要创建多个类来实现装饰器。

  2. 可能会导致性能问题:由于装饰器是通过递归来实现的,可能会对性能产生一定的影响,尤其是在多层嵌套的情况下。

  3. 可能会出现装饰器的堆叠问题:当多个装饰器同时应用于同一对象时,可能会出现装饰器的堆叠问题,导致代码变得难以理解和维护。

  4. 可能会破坏对象的封装性:使用装饰器模式会暴露对象的内部细节,可能会破坏对象的封装性,导致代码变得不安全和不稳定。

应用场景

  1. 日志记录:通过装饰器模式,可以在不改变原有代码的情况下,给函数或方法添加日志记录的功能,方便调试和排查问题。

  2. 缓存处理:通过装饰器模式,可以给函数或方法添加缓存功能,避免重复计算或访问数据库等资源,提高程序性能。

  3. 身份验证:通过装饰器模式,可以给函数或方法添加身份验证的功能,确保只有授权用户才能访问某些敏感数据或功能。

  4. 授权管理:通过装饰器模式,可以给函数或方法添加授权管理的功能,确保只有授权用户才能执行某些操作,防止非法访问或操作。

  5. 计时器:通过装饰器模式,可以给函数或方法添加计时器功能,记录函数或方法的执行时间,方便性能优化。

  6. 错误处理:通过装饰器模式,可以给函数或方法添加错误处理的功能,确保程序在出现异常时能够正确处理并返回错误信息。

代码实现

import time

def timer(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"Function func.__name__ took end_time - start_time seconds to run.")
        return result
    return wrapper

@timer
def my_function():
    # some code here
    time.sleep(1)

my_function()

注:python中一切皆对象,函数也是对象

Python 装饰器实现单列模式

# 使用装饰器实现单列模式
def singleton(cls):

    # 用来存在实例的字典
    singleton_instance = {}

    def wrapper(*args, **kwargs):
        # 判断字典中是否实例
        if not singleton_instance.get(cls.__name__): 
            # 没有则创建一个实例,并存入字典中
            singleton_instance[cls.__name__] = cls(*args, **kwargs)
        # 返回已经创建的实例
        return singleton_instance[cls.__name__]
    return wrapper


@singleton
class A(object):
    def __init__(self):
        print("__init__")

    def test(self):
        print("test")


print(A) 
print(id(A()))
print(id(A()))
A().test()

输出
<function singleton.<locals>.wrapper at 0x000002203FE44D08>
__init__
2337533963008
2337533963008
test

总结:

1、定义一个装饰器,在装饰器内部返回一个该类的对象皆可(如果已经有了,则返回之前创建的,所有需要一个字典来存储)

2、类被装饰器装饰以后,其类型已经被更改为 function 类型了

说明:cls.__name__ 可以任意命名,保持一致即可

以上是关于python设计模式6装饰器模式的主要内容,如果未能解决你的问题,请参考以下文章

python设计模式6装饰器模式

Python基础篇第6篇: Python装饰器

python笔记第九天 装饰器

Python 装饰器和装饰器模式有啥区别?

python装饰器三种装饰模式的简单理解

python-装饰器模式