设计模式(c++)-结构型模式-装饰器模式

设计模式(C++)-结构型模式-装饰器模式

一、装饰器模式概述

装饰器模式(Decorator Pattern)是一种结构型设计模式,核心目标是在不修改原有类的基础上,动态地给对象添加新功能的行为。它通过创建一系列"装饰器"类来包装原始对象,形成一个可递归嵌套的对象链,从而实现功能的灵活组合。

核心原则:对扩展开放,对修改关闭(OCP)。用组合代替继承,避免"子类爆炸"。

二、装饰器模式UML类图

三、代码实现

cpp 复制代码
/*Decorator模式(装饰器模式)
 装饰器模式(Decorator Pattern)是一种结构型设计模式,核心目标是在不修改原有类的基础上,
 动态地给对象添加新功能的行为。它通过创建一系列"装饰器"类来包装原始对象,形成一个
 可递归嵌套的对象链,从而实现功能的灵活组合。
 核心原则:对扩展开放,对修改关闭(OCP)。用组合代替继承,避免"子类爆炸"。
*/
#pragma once
#include <string>
#include <memory>
//1.IComponent:抽象接口
class IComponent {
public:
	virtual ~IComponent() = default;
	virtual void operation(std::string&data)const = 0;
};
//2.接口实现
class TextProcessor :public IComponent {
public:
	void operation(std::string&data)const override;
};

//3.Decorator:抽象装饰器基类
class Decorator :public IComponent {
protected:
	std::unique_ptr<IComponent> wrapped_; //被包装的对象
public:
	explicit Decorator(std::unique_ptr<IComponent>comp) :wrapped_(std::move(comp)) {}
	//默认转发,字类可重写
	void operation(std::string&data)const override;
};

//4.ConcreateDecoratorA:添加前缀
class PrefixDecorator :public Decorator {
	std::string prefix_;
public:
	PrefixDecorator(std::unique_ptr<IComponent>comp, std::string prefix)
		:Decorator(std::move(comp)), prefix_(prefix) {}
	void operation(std::string&data)const override;
};

//5.ConcreateDecoratorB:反转字符串
class ReverseDecorator :public Decorator {
public:
	//使用基类构造函数
	using Decorator::Decorator;
	void operation(std::string&data)const override;
};

//6:统计长度装饰器
class LengthStateDecorator :public Decorator {
public:
	using Decorator::Decorator;
	void operation(std::string&data)const override;
};

void testDecorator();

//Decorator.cc
#include "Decorator.h"
#include <iostream>
#include <cctype>

//接口实现
void TextProcessor::operation(std::string&data)const {
	std::cout << "[TextProcessor] Processing: " << data << std::endl;
	//基础处理:转大写
	for (auto&c : data) c = std::toupper(c);
}

//抽象装饰器 //默认转发,子类可重写
void Decorator::operation(std::string&data)const {
	if (wrapped_) wrapped_->operation(data);
}

//添加前缀装饰器
void PrefixDecorator::operation(std::string&data)const {
	data = prefix_ + ">>" + data;
	Decorator::operation(data);//调用父类接口转发
}

//反转字符串
void  ReverseDecorator::operation(std::string&data)const {
	Decorator::operation(data); //先执行原操作
	std::reverse(data.begin(), data.end());
}

//统计长度装饰器
void LengthStateDecorator::operation(std::string&data)const {
	Decorator::operation(data);
	std::cout << "[Length] After processing:" << data.length() << "chars" << std::endl;
}

//调用测试
void testDecorator() {

	std::cout << "=================Decorator Begin===============" <<std::endl;
	std::string input = "hello world";
	std::cout << "=== 原始处理===" << std::endl;
	auto processor = std::make_unique<TextProcessor>();
	auto copy1 = input;
	processor->operation(copy1);
	std::cout << "Result: " << copy1 << std::endl;

	std::cout << "=== 装饰器链:前缀->大写->反转===" << std::endl;
	auto decorated = std::make_unique<ReverseDecorator>(
		std::make_unique<PrefixDecorator>(
			std::make_unique<TextProcessor>(),
			"Start"
			)
		);
	auto copy2 = input;
	decorated->operation(copy2);
	std::cout << "Result: " << copy2 << std::endl;

	std::cout << " === 加上统计装饰器===" << std::endl;
	auto withStats = std::make_unique<LengthStateDecorator>(
		std::make_unique<ReverseDecorator>(
		std::make_unique<PrefixDecorator>(
			std::make_unique<TextProcessor>(),
			"Demo")
		));
	auto copy3 = input;
	withStats->operation(copy3);
	std::cout << "Final: " << copy3 << std::endl;
	std::cout << "=================Decorator End===============" << std::endl;
}

四 、优缺点总结

优点

  • 比继承更灵活:避免为每项功能组合创建子类
  • 运行时动态装配:可随时增减装饰器
  • 单一职责:每个装饰器只关注一种增强逻辑
  • 类型透明:客户端无需区分原始对象与 装饰器

缺点

  • 过度使用会增加微小对象数量,带来堆内存开销
  • 调用链过长影响性能,必要时可用责任链模式优化
相关推荐
纪念 22924 分钟前
C++类和对象(二)
开发语言·c++
钓鱼的肝33 分钟前
csp-j-s总结(1)
c++·笔记·算法·青少年编程
Zane199439 分钟前
MVC 三层架构被打上反模式标签?一次账户扣款需求,讲清楚贫血模型和充血模型该怎么选
设计模式
linx2951 小时前
第七章 · 标准库容器、算法与 ranges
c语言·开发语言·数据结构·c++·算法
钓鱼的肝1 小时前
csp-j-s总结(4)
c++·经验分享·笔记·算法
别动我齐刘海2 小时前
ROS2 Jazzy + C++ 实战路线——基础学习1
c++·vscode·python·ubuntu·机器学习·自动驾驶·github
j7~2 小时前
【Linux网络加餐】(篇七)网络版计算器(中):协议落地、报文分隔与完整链路
linux·c++·网络编程·tcp·报文分割·网络计算器·协议落地
青少儿编程课堂2 小时前
多源最短路与最小环(Floyd 算法图论解析)
c++·python·算法·bfs·信息学竞赛
6Hzlia2 小时前
【Classic 150 刷题计划】 LeetCode 228. 汇总区间 | C++ 锚点游标与断点检测法
c++·算法·leetcode
Severus_black2 小时前
【C++初阶】模板初阶——为何C++能和C语言拉开差距?
c++