文本是《设计模式(共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 篇。请继续阅读该专题下面的文章:
