设计模式概述
Decorator 设计模式 允许我们通过组合的方式动态地为对象添加新功能,而无需修改对象的代码。该模式由以下几个角色组成:
- Component(组件):定义了一个接口,用于定义所有对象的公共操作。
- ConcreteComponent(具体组件):实现了组件接口的类,表示要被装饰的对象。
- Decorator(装饰器):继承自组件接口,并在内部持有一个组件实例,用来包装(装饰)原始组件。
- ConcreteDecorator(具体装饰器):具体的装饰器,添加额外的行为或功能。
UML 图(使用 Markdown text 标签绘制)
+-------------------+ +-------------------+
| Component |<>------| Decorator |
+-------------------+ +-------------------+
^ ^
| |
+---------------------+ +----------------------+
| ConcreteComponent | | ConcreteDecorator |
+---------------------+ +----------------------+
设计模式实现
在 Python 中,我们可以使用装饰器模式来动态地添加功能。下面的例子展示了如何通过装饰器给 SimpleCoffee
类添加新功能:
Python 实现示例
from abc import ABC, abstractmethod
# 组件接口
class Coffee(ABC):
@abstractmethod
def cost(self):
pass
# 具体组件
class SimpleCoffee(Coffee):
def cost(self):
return 5 # 简单咖啡的价格
# 装饰器基类
class CoffeeDecorator(Coffee):
def __init__(self, coffee: Coffee):
self._coffee = coffee # 组合具体的咖啡对象
@abstractmethod
def cost(self):
pass
# 具体装饰器 1: 加奶
class MilkDecorator(CoffeeDecorator):
def cost(self):
return self._coffee.cost() + 2 # 加奶的价格
# 具体装饰器 2: 加糖
class SugarDecorator(CoffeeDecorator):
def cost(self):
return self._coffee.cost() + 1 # 加糖的价格
# 客户端代码
coffee = SimpleCoffee()
print(f"Simple Coffee cost: ${coffee.cost()}")
# 使用装饰器
milk_coffee = MilkDecorator(coffee)
print(f"Milk Coffee cost: ${milk_coffee.cost()}")
sugar_milk_coffee = SugarDecorator(milk_coffee)
print(f"Milk Coffee with Sugar cost: ${sugar_milk_coffee.cost()}")
代码解释
Coffee
接口定义了所有具体咖啡类必须实现的cost()
方法。SimpleCoffee
类是基础的咖啡类,计算其基本价格。CoffeeDecorator
是装饰器的基类,所有具体的装饰器都将继承这个类,并实现cost()
方法。MilkDecorator
和SugarDecorator
是具体的装饰器,分别为咖啡添加奶和糖,计算新的价格。- 客户端代码演示了如何通过装饰器来动态地给
SimpleCoffee
添加不同的功能(奶和糖)。
输出
Simple Coffee cost: $5
Milk Coffee cost: $7
Milk Coffee with Sugar cost: $8
优点
- 灵活性高:可以在运行时决定是否使用装饰器,动态增加功能。
- 避免子类化:通过装饰器组合方式增加功能,而不必通过继承。
- 符合开闭原则:可以通过添加新的装饰器来扩展功能,而不需要修改已有代码。
缺点
- 装饰器数量过多时会增加复杂性:如果装饰器太多,可能会导致系统过于复杂,难以理解。
- 每次装饰都会创建新的对象:可能会引入一些额外的对象创建和性能开销。
总结
Decorator 模式 是一种非常灵活的设计模式,它允许我们在不修改原有类的基础上,动态地为对象添加新的行为。通过组合多个装饰器,我们可以高效地扩展对象的功能,避免过度使用继承。该模式广泛应用于图形界面、输入输出流、缓存、网络协议等领域。