1.装饰器模式(Decorator Pattern)的定义
装饰器模式是一种结构型设计模式,其核心思想是:
- 动态地给对象添加额外功能,而不改变其原有结构
- 通过**包装(wrapping)**原始对象来提供增强功能
- 遵循开闭原则(对扩展开放,对修改关闭)
UML核心组件:
- Component:定义原始对象的接口
- ConcreteComponent:原始对象的具体实现
- Decorator:持有Component引用并实现相同接口
- ConcreteDecorator:具体的装饰器实现
2.背景
我在搭建python测试框架时,无论是unittest还是pytest,均提供了装饰器模式,对function加入装饰器声明包装,使得function成为待使用的case
3.Python装饰器(Decorator)的实现
Python中的装饰器语法(@decorator
)是装饰器模式的一种语法糖实现,但二者并不完全等同:
python
def decorator(func):
def wrapper(*args, **kwargs):
print("Before function") # 添加新功能
result = func(*args, **kwargs) # 调用原函数
print("After function") # 添加新功能
return result
return wrapper
@decorator
def original_function():
print("Original function")
4.测试框架中的"装饰器模式"应用
1) pytest的实现方式
python
@pytest.mark.slow
def test_function():
pass
- 本质 :
pytest.mark.slow
是一个函数装饰器,它给测试函数添加了元数据 - 装饰器模式体现 :
- 原始组件:测试函数
- 装饰器:
pytest.mark
系统 - 新增功能:添加标记(mark)信息到测试函数
2) unittest的实现方式
python
@unittest.skip("reason")
def test_method(self):
pass
- 本质 :
unittest.skip
是一个类装饰器(实际是描述符协议实现) - 装饰器模式体现 :
- 原始组件:测试方法
- 装饰器:
unittest.skip
等装饰器 - 新增功能:改变测试方法的执行行为(如跳过测试)
5.为什么说这是装饰器模式?
虽然测试框架中的装饰器使用看起来像是简单的语法装饰器,但它们实际上符合装饰器模式的核心思想:
-
不修改原测试函数/方法:保持原始测试逻辑不变
-
动态添加功能 :
- pytest:添加标记、参数化、fixture依赖等
- unittest:添加跳过、预期失败等行为
-
多层包装能力 :
python@pytest.mark.slow @pytest.mark.parametrize("input", [1,2,3]) def test_func(input): pass
6.上位机中的装饰器模式
下面展示一个在QT上位机应用中使用装饰器模式的完整示例。这个例子模拟了一个数据可视化系统,可以动态地给数据处理器添加不同的功能(如日志记录、数据验证、加密等)。
场景描述
数据处理器可以动态添加以下功能:
- 日志记录功能
- 数据验证功能
- 数据加密功能
实现代码
cpp
#include <QCoreApplication>
#include <QDebug>
#include <QString>
#include <memory>
// 抽象组件接口
class DataProcessor {
public:
virtual ~DataProcessor() = default;
virtual QString process(const QString& data) = 0;
};
// 具体组件 - 核心数据处理功能
class CoreDataProcessor : public DataProcessor {
public:
QString process(const QString& data) override {
qDebug() << "Core processing data:" << data;
// 模拟核心处理逻辑
return data.toUpper();
}
};
// 抽象装饰器
class DataProcessorDecorator : public DataProcessor {
protected:
std::unique_ptr<DataProcessor> processor;
public:
DataProcessorDecorator(std::unique_ptr<DataProcessor> processor)
: processor(std::move(processor)) {}
};
// 具体装饰器 - 日志记录
class LoggingDecorator : public DataProcessorDecorator {
public:
using DataProcessorDecorator::DataProcessorDecorator;
QString process(const QString& data) override {
qDebug() << "Logging: Before processing -" << data;
QString result = processor->process(data);
qDebug() << "Logging: After processing -" << result;
return result;
}
};
// 具体装饰器 - 数据验证
class ValidationDecorator : public DataProcessorDecorator {
public:
using DataProcessorDecorator::DataProcessorDecorator;
QString process(const QString& data) override {
if(data.isEmpty()) {
qWarning() << "Validation failed: Empty data";
return "";
}
return processor->process(data);
}
};
// 具体装饰器 - 数据加密
class EncryptionDecorator : public DataProcessorDecorator {
QString encrypt(const QString& data) {
// 简单加密示例 - 实际应用中替换为真正的加密算法
QString result;
for(QChar ch : data) {
result.append(QChar(ch.unicode() + 1));
}
return result;
}
QString decrypt(const QString& data) {
// 简单解密
QString result;
for(QChar ch : data) {
result.append(QChar(ch.unicode() - 1));
}
return result;
}
public:
using DataProcessorDecorator::DataProcessorDecorator;
QString process(const QString& data) override {
QString encrypted = encrypt(data);
qDebug() << "Encrypted data:" << encrypted;
QString processed = processor->process(encrypted);
return decrypt(processed);
}
};
// QT上位机应用示例
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建基础处理器
std::unique_ptr<DataProcessor> processor = std::make_unique<CoreDataProcessor>();
// 动态添加功能
bool enableLogging = true;
bool enableValidation = true;
bool enableEncryption = true;
if(enableLogging) {
processor = std::make_unique<LoggingDecorator>(std::move(processor));
}
if(enableValidation) {
processor = std::make_unique<ValidationDecorator>(std::move(processor));
}
if(enableEncryption) {
processor = std::make_unique<EncryptionDecorator>(std::move(processor));
}
// 模拟上位机数据处理
QString testData = "Hello QT Decorator Pattern";
qDebug() << "Original data:" << testData;
QString result = processor->process(testData);
qDebug() << "Final result:" << result;
// 测试空数据验证
qDebug() << "\nTesting empty data validation:";
processor->process("");
return a.exec();
}
输出示例
Original data: "Hello QT Decorator Pattern"
Encrypted data: "Ifmmp!RU!Efdpsojps!Qbssfsu"
Logging: Before processing - "Ifmmp!RU!Efdpsojps!Qbssfsu"
Core processing data: "Ifmmp!RU!Efdpsojps!Qbssfsu"
Logging: After processing - "IFMMP!RU!EFDPSOJPS!QBSSFSU"
Final result: "HELLO QT DECORATOR PATTERN"
Testing empty data validation:
Validation failed: Empty data
关键点解析
- 组件接口 :
DataProcessor
定义了核心接口 - 具体组件 :
CoreDataProcessor
实现基础功能 - 装饰器基类 :
DataProcessorDecorator
持有被装饰对象的指针 - 具体装饰器 :
LoggingDecorator
添加日志功能ValidationDecorator
添加数据验证EncryptionDecorator
添加加密/解密功能
- 动态组合:在运行时根据需要组合各种功能
QT实际应用场景
- 通信协议栈:可以动态添加CRC校验、数据压缩、加密等层
- UI组件增强:为基本控件添加动画、阴影等效果
- 数据处理流水线:动态组合不同的数据处理算法
- 插件系统:通过装饰器模式动态扩展功能
这种模式在QT上位机开发中特别有用,因为它允许灵活地组合功能而不需要修改现有代码,符合开闭原则。