【第八节】C++设计模式(结构型模式)-Decorator(装饰器)模式
目录
一、问题引出
二、模式选择
三、代码实现
四、总结讨论
一、问题引出
装饰器模式:动态扩展对象功能的设计模式
在面向对象(OO)设计与开发中,我们常面临为已有类添加新职责的需求。传统方法是通过继承创建子类来实现功能扩展,但这种方式容易导致继承层次过深,显著增加系统复杂度。装饰器模式(Decorator Pattern)应运而生,其通过组合替代继承的机制,为功能扩展提供了更灵活的解决方案,从而避免了继承层次过深带来的复杂性。
二、模式选择
装饰器模式的典型结构图如下:
在结构中,ConcreteComponent
(具体组件)和 Decorator
(装饰器)均继承自 Component
基类,共享统一接口。可能有人质疑:为何不直接让 Decorator
持有 ConcreteComponent
的指针来实现扩展?答案是此方式仅支持单一组件类型。若新增其他组件类型(如 AnotherConcreteComponent
),则需重新定义新的装饰器类,违背开闭原则。而通过共享 Component
基类,装饰器可借助多态特性,适配所有子类对象,实现通用扩展能力。这正是装饰器模式的核心优势。
注:若仅需为单一组件类型添加功能,可省略
Decorator
基类,直接实现具体装饰器。
三、代码实现
装饰器模式的实现并不复杂,下面是一个完整的代码示例(采用 C++ 实现)。
代码片段 1:Decorator.h
#ifndef _DECORATOR_H_
#define _DECORATOR_H_
// 抽象组件基类
class Component {
public:
virtual ~Component() {}
virtual void Operation() = 0; // 纯虚接口
protected:
Component() {} // 允许子类构造
};
// 具体组件类
class ConcreteComponent : public Component {
public:
void Operation() override; // 实现基类接口
};
// 抽象装饰器基类
class Decorator : public Component {
public:
Decorator(Component* com) : _com(com) {}
virtual ~Decorator() { delete _com; } // 管理组件生命周期
void Operation() override; // 委托给组件对象
protected:
Component* _com; // 组合的组件对象
};
// 具体装饰器类
class ConcreteDecorator : public Decorator {
public:
ConcreteDecorator(Component* com) : Decorator(com) {}
void Operation() override;
void AddedBehavior(); // 新增扩展行为
};
#endif //~_DECORATOR_H_
代码片段 2:Decorator.cpp
#include "Decorator.h"
#include <iostream>
// 具体组件实现
void ConcreteComponent::Operation() {
std::cout << "ConcreteComponent: 基础操作" << std::endl;
}
// 装饰器默认实现(可省略)
void Decorator::Operation() {
if (_com) _com->Operation(); // 委托调用
}
// 具体装饰器扩展实现
void ConcreteDecorator::Operation() {
Decorator::Operation(); // 调用原有功能
AddedBehavior(); // 添加新行为
}
void ConcreteDecorator::AddedBehavior() {
std::cout << "ConcreteDecorator: 新增扩展行为" << std::endl;
}
代码片段 3:main.cpp
#include "Decorator.h"
int main() {
Component* component = new ConcreteComponent(); // 创建基础组件
Component* decorated = new ConcreteDecorator(component); // 动态装饰
decorated->Operation(); // 执行扩展后的操作
delete decorated; // 释放资源(自动递归删除组件)
return 0;
}
代码解析
组件与装饰器关系
ConcreteComponent 实现基础功能,ConcreteDecorator 通过组合持有组件对象,并在其操作前后添加新行为。
装饰器类继承自 Component,保证接口一致性,支持嵌套装饰(如DecoratorA(DecoratorB(Component)))。
生命周期管理
装饰器负责管理其持有的组件对象(delete _com),客户端仅需释放最外层装饰器,避免内存泄漏。
输出结果
ConcreteComponent: 基础操作
ConcreteDecorator: 新增扩展行为
四、总结讨论
模式对比:装饰器 vs 代理 vs 组合
若装饰器仅持有具体组件(非抽象接口),其结构将与代理模式高度相似,但两者意图截然不同。
装饰器模式与组合模式(Composite Pattern)在结构上有些相似,但它们的主要区别在于应用场景和目的。装饰器模式与代理模式(Proxy Pattern)在某些方面也有相似之处。虽然它们在结构图上并不相似,但如果让 `Decorator` 直接持有一个 `ConcreteComponent` 的引用(指针),其结构图就与代理模式非常相似了。
由此,装饰器模式与代理模式的相似之处在于,它们都通过组合的方式持有一个指向其他对象的引用(指针)。不同之处在于,代理模式通常会提供与其代理对象相同的接口,并将操作直接委托给代理对象执行。而装饰器模式则通过组合的方式动态地为对象添加新的职责。
装饰器模式不仅通过组合的方式避免了继承带来的复杂性,还为设计提供了一种“即用即付”的方式来添加职责。在 OO 设计和分析中,常常会遇到这样的情况:为了多态性,通过父类指针指向其具体子类,但当具体子类需要添加新的职责时,就必须在父类中添加相应的抽象接口。这会导致父类承载过多的职责,并且所有子类都会继承这些接口,即使它们并不需要。装饰器模式通过动态添加职责的方式,很好地解决了这一问题。由此总结其核心优势与适用场景如下:
优势
(1)动态扩展:运行时灵活添加功能,避免静态继承的臃肿。
(2)接口一致性:装饰后对象仍为 Component 类型,兼容原有逻辑。
(3)职责分离:每个装饰器仅关注单一扩展点,符合单一职责原则。
适用场景
(1)需为对象添加可选或可拆卸功能(如日志、缓存、权限校验)。
(2)无法通过继承扩展(如 final 类)或继承会导致类爆炸。
装饰器模式通过组合+委托的机制,实现了对象功能的动态扩展。其核心在于:
(1)开放-封闭原则:无需修改原有代码,通过新增装饰器扩展功能。
(2)接口抽象:统一组件与装饰器的接口,支持多态嵌套。
(3)灵活替代继承:避免深度继承层次,降低系统复杂度。
该模式尤其适用于框架设计或需要高频扩展的场景,是面向对象设计中“组合优于继承”理念的经典实践。