文本是《设计模式(共12篇)》专题的第 7 篇。阅读本文前,建议先阅读前面的文章:
装饰者模式详解 - Python版本
1️⃣ 概念
定义:在不改变原有对象的基础上,将功能附加到对象上;提供了比继承更有弹性的替代方案(扩展原有对象功能)。
类型:结构性
2️⃣ 适用场景
- 扩展一个类的功能或者给一个类添加附加职责
 - 动态的给一个对象添加功能,这些功能可以在动态的撤销
 
3️⃣ 优点
- 继承的有力补充,比继承灵活,不改变原有对象的情况下给一个对象扩展功能
 - 通过使用不同的装饰类以及这些装饰类的排列组合,可以实现不同的效果
 - 符合开闭原则
 
4️⃣ 缺点
- 会出现更多的代码,更多的类,增加程序的复杂性
 - 动态装饰时以及多层装饰时会更复杂
 
5️⃣ 装饰者模式 Coding
v1版本
① 创建基础类
class Battercake:
    def get_desc(self):
        return "煎饼"
    def cost(self):
        return 8
② 创建扩展类继承基础类
class BattercakeWithEgg(Battercake):
    def get_desc(self):
        return super().get_desc() + " 加一个鸡蛋"
    def cost(self):
        return super().cost() + 1
③ 创建扩展类继承①和②
class BattercakeWithEggSausage(BattercakeWithEgg):
    def get_desc(self):
        return super().get_desc() + " 加一根香肠"
    def cost(self):
        return super().cost() + 2
④ 创建测试类
def test():
    battercake = Battercake()
    print(f"{battercake.get_desc()} 销售价格:{battercake.cost()}")
    battercake_with_egg = BattercakeWithEgg()
    print(f"{battercake_with_egg.get_desc()} 销售价格:{battercake_with_egg.cost()}")
    battercake_with_egg_sausage = BattercakeWithEggSausage()
    print(f"{battercake_with_egg_sausage.get_desc()} 销售价格:{battercake_with_egg_sausage.cost()}")
if __name__ == "__main__":
    test()
说明:使用这样的方式来进行扩展的话,如果组合非常的多我们的程序会发生类爆炸的情况,怎么样才能让我们的程序更加的优雅呢?请往下看。
v2版本
① 创建抽象基类
from abc import ABC, abstractmethod
class ABattercake(ABC):
    @abstractmethod
    def get_desc(self):
        pass
    @abstractmethod
    def cost(self):
        pass
② 创建抽象装饰类继承①
class AbstractDecorator(ABattercake):
    def __init__(self, a_battercake):
        self.a_battercake = a_battercake
    @abstractmethod
    def do_something(self):
        pass
    def get_desc(self):
        return self.a_battercake.get_desc()
    def cost(self):
        return self.a_battercake.cost()
③ 创建实体类继承①并实现抽象方法
class Battercake(ABattercake):
    def get_desc(self):
        return "煎饼"
    def cost(self):
        return 8
④ 创建鸡蛋装饰类继承②并实现抽象方法
class EggDecorator(AbstractDecorator):
    def __init__(self, a_battercake):
        super().__init__(a_battercake)
    def do_something(self):
        pass
    def get_desc(self):
        return super().get_desc() + " 加一个鸡蛋"
    def cost(self):
        return super().cost() + 1
⑤ 创建香肠装饰类继承②并实现抽象方法
class SausageDecorator(AbstractDecorator):
    def __init__(self, a_battercake):
        super().__init__(a_battercake)
    def do_something(self):
        pass
    def get_desc(self):
        return super().get_desc() + " 加一根香肠"
    def cost(self):
        return super().cost() + 2
⑥ 编写测试代码
def test():
    a_battercake = Battercake()
    a_battercake = EggDecorator(a_battercake)
    a_battercake = EggDecorator(a_battercake)
    a_battercake = SausageDecorator(a_battercake)
    print(f"{a_battercake.get_desc()} 销售价格:{a_battercake.cost()}")
if __name__ == "__main__":
    test()
说明:由于每个实体类都继承了抽象类①,所以我们在使用的时候可以直接创建,也就是说所有的实体类都是ABattercake的子类;另外关于do_something方法,可以理解成每个实体类进行操作前的一个动作,便于扩展。
6️⃣ 装饰者模式的实际应用
① Python标准库中的使用
Python中装饰者模式的应用非常广泛,最常见的例子包括:
文件操作装饰器:
# Python中类似Java IO的装饰器模式示例
import io
# 基础文件流
with open('file.txt', 'r') as f:
    # 使用缓冲装饰器
    buffered_reader = io.BufferedReader(f)
    # 可以继续添加其他装饰器
内置装饰器:
# @property 装饰器
class Circle:
    def __init__(self, radius):
        self._radius = radius
    @property
    def radius(self):
        return self._radius
    @radius.setter
    def radius(self, value):
        self._radius = value
# @staticmethod 和 @classmethod 装饰器
class MyClass:
    @staticmethod
    def static_method():
        return "静态方法"
    @classmethod
    def class_method(cls):
        return "类方法"
7️⃣ Python函数装饰器示例
Python还提供了函数装饰器的语法糖:
# 简单的函数装饰器示例
def timing_decorator(func):
    import time
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 执行时间: {end_time - start_time:.4f}秒")
        return result
    return wrapper
@timing_decorator
def slow_function():
    import time
    time.sleep(1)
    return "执行完成"
# 使用装饰器
result = slow_function()
您已阅读完《设计模式(共12篇)》专题的第 7 篇。请继续阅读该专题下面的文章:
