广告
您当前的位置: 首页 >  技术 >  Python

Python 深入浅出:设计模式中的“装饰器”与 Python “装饰器”的异同

作者:XiaoZhang 时间:2026-06-28 阅读数:9人阅读

在面向对象编程中,“装饰器”是一个经常引起混淆的词汇。

当开发者阅读经典的《设计模式:可复用面向对象软件的基础》(GoF)一书时,会读到 “装饰器模式(Decorator Pattern)”;而当他们学习 Python 语言时,又会遇到以 @ 符号为代表的 “Python 装饰器(Decorators)”

这两者虽然名字完全相同,但在概念设计、实现机制以及应用层面上其实有着明显的异同。

本文将带您理清设计模式中的“装饰器”与 Python 语言中的“装饰器”之间的恩怨纠葛。


一、 GoF 设计模式中的“装饰器模式”

1. 核心意图

在不改变原有类结构、也不使用继承的前提下,动态地给一个实例对象添加一些额外的职责(功能)。它是通过组合(Composition)代替继承来实现扩展的经典范式。

2. 结构特征

  • 接口一致性:装饰器类和被装饰的组件类必须继承自同一个抽象基类(接口)
  • 嵌套包装:装饰器内部持有一个组件对象的引用,在执行自身逻辑前后,调用被包装对象的方法。
classDiagram
    class Component {
        <<interface>>
        +operation()
    }
    class ConcreteComponent {
        +operation()
    }
    class Decorator {
        -Component component
        +operation()
    }
    class ConcreteDecoratorA {
        +operation()
    }
    Component <|-- ConcreteComponent
    Component <|-- Decorator
    Decorator o-- Component
    Decorator <|-- ConcreteDecoratorA

二、 Python 语言中的“装饰器”

1. 核心意图

Python 中的装饰器是一种语言级别的语法糖。它本质上是一个高阶函数:接受一个可调用对象(函数或类)作为入参,并返回一个新的可调用对象

2. 结构特征

  • 语法糖 @@my_decorator 只是 func = my_decorator(func) 的简化写法。
  • 定义期生效:Python 装饰器在模块加载、函数被定义时就立即执行并完成了包装,而不是在对象运行时动态包装。
def my_decorator(func):
    def wrapper(*args, **kwargs):
        print("执行前...")
        result = func(*args, **kwargs)
        print("执行后...")
        return result
    return wrapper

@my_decorator
def say_hello():
    pass

三、 深度对比:两者的本质异同

我们从三个维度来剖析它们之间的差异:

维度 GoF 装饰器模式 Python 装饰器
本质属性 一种架构设计模式(思想) 一种语法特性(语法糖)
作用粒度 对象级别(Object-level)。只对被包装的某一个特定实例生效,其他同类实例不受影响。 定义级别(Definition-level)。对被装饰的函数或类模板整体生效,所有生成的实例全部被改变。
类型约束 极强。包装后对象的类型(接口)必须保持一致,以便多层嵌套。 极弱。Python 作为动态语言,装饰器甚至可以返回一个与原函数完全不同类型、不同签名的对象。

四、 用 Python 实现 GoF 装饰器模式

在 Python 中,因为其动态性,实现传统的 GoF 装饰器模式非常简单,甚至不需要繁琐的接口声明:

# 1. 基础组件:咖啡
class Coffee:
    def get_cost(self):
        return 10

    def get_ingredients(self):
        return "咖啡"

# 2. 装饰器基类(保持接口一致,并持有被包装对象)
class CoffeeDecorator:
    def __init__(self, coffee):
        self._coffee = coffee

    def get_cost(self):
        return self._coffee.get_cost()

    def get_ingredients(self):
        return self._coffee.get_ingredients()

# 3. 具体装饰器:加奶
class MilkDecorator(CoffeeDecorator):
    def get_cost(self):
        # 基础费用 + 牛奶费用 2 元
        return super().get_cost() + 2

    def get_ingredients(self):
        return super().get_ingredients() + ", 加奶"

# 运行期动态包装单例对象
my_coffee = Coffee()
print(f"{my_coffee.get_ingredients()} 的价格: {my_coffee.get_cost()} 元")

# 动态加上牛奶装饰
my_milk_coffee = MilkDecorator(my_coffee)
print(f"{my_milk_coffee.get_ingredients()} 的价格: {my_milk_coffee.get_cost()} 元")

上面的 MilkDecorator 结构就是经典的 GoF 装饰器模式。它是在运行期,通过把 my_coffee 对象塞入 MilkDecorator 的构造函数中,实现了动态扩展。


五、 总结

  1. GoF 装饰器模式是一种设计思想,强调在运行期对单个实例对象进行组合式的功能叠加。
  2. Python 装饰器是一种语法糖,强调在编译/定义期对函数或类模板进行切面注入(AOP)。
  3. 在 Python 编码中,我们可以用 Python 装饰器(语法糖)来优雅地生成和辅助实现 GoF 装饰器模式,两者相辅相成。

理清这两个概念的异同,能让您在进行面向对象架构设计与 Python 编程时,思路更加清晰,表达更加准确!

本站所有文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。

评论交流 (0)

正在加载评论...
头像

XiaoZhang

当你还撑不起你的梦想时,就要去奋斗。如果缘分安排我们相遇,请不要让她擦肩和过。我们一起奋斗!

微信