结构型模式:④装饰模式(Decorator Pattern)
核心思想
动态地给对象添加额外职责,无需修改原对象的类结构,也无需创建大量子类(避免 “子类爆炸”)。核心是通过「组合关系」替代「继承关系」:
抽象组件(Component):定义被装饰对象的统一接口;
具体组件(ConcreteComponent):基础对象(被装饰的核心);
抽象装饰器(Decorator):持有抽象组件的引用,实现抽象组件接口(确保与被装饰对象接口一致);
具体装饰器(ConcreteDecorator):继承抽象装饰器,在转发调用基础上添加额外职责。
核心本质
包装(Wrap)+ 转发(Delegate)+ 扩展(Extend),客户端可通过嵌套装饰器动态组合多个额外职责。
C语言编写
场景示例
咖啡订单系统:
抽象组件(CoffeeComponent):定义咖啡的统一接口(获取描述、获取价格);
具体组件(Americano):基础咖啡(美式咖啡,无额外配料);
抽象装饰器(CoffeeDecorator):持有咖啡组件指针,实现统一接口;
具体装饰器(MilkDecorator、SugarDecorator):给咖啡加牛奶、加糖,添加额外价格和描述。
关键要点
1.接口统一:抽象组件(CoffeeComponent)定义 GetDesc/GetPrice 统一接口,基础咖啡和所有装饰器都实现该接口,确保客户端操作一致。
2.组合核心:抽象装饰器(CoffeeDecorator)通过成员指针 component 持有被装饰对象(基础咖啡或已装饰的咖啡),替代继承实现功能复用。
3.转发 + 扩展:具体装饰器(如 MilkDecorator)先转发调用被装饰对象的接口(获取基础描述 / 价格),再添加额外逻辑(加价、追加描述),实现 “不修改原对象” 的扩展。
4.嵌套装饰:客户端可通过多次嵌套装饰器(create_milk_decorator → create_sugar_decorator)动态组合多个额外职责,灵活性极高。
5.内存安全:抽象装饰器的 Destroy 方法需递归销毁被装饰对象,避免仅销毁装饰器导致的底层组件内存泄漏。
6.开闭原则:新增配料(如 “奶泡”)时,只需新增 FoamDecorator 具体装饰器,无需修改基础咖啡类和现有装饰器。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 最大描述长度(简化示例)
#define MAX_DESC 128
// -------------------------- 1. 抽象组件(Component):咖啡统一接口 --------------------------
typedef struct CoffeeComponent {
// 统一接口:获取咖啡描述
void (*GetDesc)(struct CoffeeComponent* self, char* desc);
// 统一接口:获取咖啡价格
float (*GetPrice)(struct CoffeeComponent* self);
void (*Destroy)(struct CoffeeComponent* self);
} CoffeeComponent;
// -------------------------- 2. 具体组件(ConcreteComponent):基础咖啡(美式) --------------------------
typedef struct Americano {
CoffeeComponent base; // 模拟继承:包含抽象组件接口
float price; // 基础价格
char desc[MAX_DESC]; // 基础描述
} Americano;
// 美式咖啡:获取描述
void americano_get_desc(CoffeeComponent* self, char* desc) {
Americano* coffee = (Americano*)self;
strncpy(desc, coffee->desc, MAX_DESC);
}
// 美式咖啡:获取价格
float americano_get_price(CoffeeComponent* self) {
Americano* coffee = (Americano*)self;
return coffee->price;
}
// 美式咖啡:销毁
void americano_destroy(CoffeeComponent* self) {
if (self != NULL) {
free(self);
}
}
// 创建基础美式咖啡
CoffeeComponent* create_americano() {
Americano* coffee = (Americano*)malloc(sizeof(Americano));
coffee->price = 15.0f;
strncpy(coffee->desc, "美式咖啡", MAX_DESC);
// 绑定抽象接口
coffee->base.GetDesc = americano_get_desc;
coffee->base.GetPrice = americano_get_price;
coffee->base.Destroy = americano_destroy;
return (CoffeeComponent*)coffee;
}
// -------------------------- 3. 抽象装饰器(Decorator):持有咖啡组件,实现统一接口 --------------------------
typedef struct CoffeeDecorator {
CoffeeComponent base; // 模拟继承:实现抽象组件接口
CoffeeComponent* component; // 组合核心:持有被装饰的咖啡组件(基础咖啡/已装饰咖啡)
} CoffeeDecorator;
// 抽象装饰器:转发获取描述(子类需重写扩展)
void decorator_get_desc(CoffeeComponent* self, char* desc) {
CoffeeDecorator* decorator = (CoffeeDecorator*)self;
// 转发调用被装饰组件的接口
decorator->component->GetDesc(decorator->component, desc);
}
// 抽象装饰器:转发获取价格(子类需重写扩展)
float decorator_get_price(CoffeeComponent* self) {
CoffeeDecorator* decorator = (CoffeeDecorator*)self;
// 转发调用被装饰组件的接口
return decorator->component->GetPrice(decorator->component);
}
// 抽象装饰器:销毁(需递归销毁被装饰组件)
void decorator_destroy(CoffeeComponent* self) {
if (self != NULL) {
CoffeeDecorator* decorator = (CoffeeDecorator*)self;
decorator->component->Destroy(decorator->component); // 销毁被装饰组件
free(self);
}
}
// 创建抽象装饰器(供具体装饰器复用初始化逻辑)
CoffeeDecorator* create_coffee_decorator(CoffeeComponent* component) {
CoffeeDecorator* decorator = (CoffeeDecorator*)malloc(sizeof(CoffeeDecorator));
// 绑定基础转发接口(具体装饰器可重写)
decorator->base.GetDesc = decorator_get_desc;
decorator->base.GetPrice = decorator_get_price;
decorator->base.Destroy = decorator_destroy;
// 绑定被装饰组件(组合关系)
decorator->component = component;
return decorator;
}
// -------------------------- 4. 具体装饰器(ConcreteDecorator):加牛奶 --------------------------
typedef struct MilkDecorator {
CoffeeDecorator base; // 模拟继承:包含抽象装饰器
float add_price; // 额外价格(牛奶加价)
char add_desc[MAX_DESC]; // 额外描述(牛奶)
} MilkDecorator;
// 加牛奶:扩展描述(基础描述 + 牛奶)
void milk_get_desc(CoffeeComponent* self, char* desc) {
MilkDecorator* decorator = (MilkDecorator*)self;
// 先转发获取被装饰组件的描述(如“美式咖啡”)
decorator->base.component->GetDesc(decorator->base.component, desc);
// 扩展描述
strncat(desc, " + 牛奶", MAX_DESC - strlen(desc) - 1);
}
// 加牛奶:扩展价格(基础价格 + 牛奶加价)
float milk_get_price(CoffeeComponent* self) {
MilkDecorator* decorator = (MilkDecorator*)self;
// 先转发获取被装饰组件的价格(如15元)
return decorator->base.component->GetPrice(decorator->base.component) + decorator->add_price;
}
// 创建“加牛奶”装饰器
CoffeeComponent* create_milk_decorator(CoffeeComponent* component) {
MilkDecorator* decorator = (MilkDecorator*)malloc(sizeof(MilkDecorator));
// 初始化抽象装饰器(绑定被装饰组件)
decorator->base = *create_coffee_decorator(component);
// 重写抽象装饰器的接口(扩展功能)
decorator->base.base.GetDesc = milk_get_desc;
decorator->base.base.GetPrice = milk_get_price;
// 额外配置(牛奶的加价和描述)
decorator->add_price = 3.0f;
strncpy(decorator->add_desc, "牛奶", MAX_DESC);
return (CoffeeComponent*)decorator;
}
// -------------------------- 5. 具体装饰器(ConcreteDecorator):加糖 --------------------------
typedef struct SugarDecorator {
CoffeeDecorator base; // 模拟继承:包含抽象装饰器
float add_price; // 额外价格(糖加价)
char add_desc[MAX_DESC]; // 额外描述(糖)
} SugarDecorator;
// 加糖:扩展描述(基础描述 + 糖)
void sugar_get_desc(CoffeeComponent* self, char* desc) {
SugarDecorator* decorator = (SugarDecorator*)self;
// 转发获取被装饰组件的描述(如“美式咖啡 + 牛奶”)
decorator->base.component->GetDesc(decorator->base.component, desc);
// 扩展描述
strncat(desc, " + 糖", MAX_DESC - strlen(desc) - 1);
}
// 加糖:扩展价格(基础价格 + 糖加价)
float sugar_get_price(CoffeeComponent* self) {
SugarDecorator* decorator = (SugarDecorator*)self;
// 转发获取被装饰组件的价格(如18元)
return decorator->base.component->GetPrice(decorator->base.component) + decorator->add_price;
}
// 创建“加糖”装饰器
CoffeeComponent* create_sugar_decorator(CoffeeComponent* component) {
SugarDecorator* decorator = (SugarDecorator*)malloc(sizeof(SugarDecorator));
// 初始化抽象装饰器(绑定被装饰组件)
decorator->base = *create_coffee_decorator(component);
// 重写抽象装饰器的接口(扩展功能)
decorator->base.base.GetDesc = sugar_get_desc;
decorator->base.base.GetPrice = sugar_get_price;
// 额外配置(糖的加价和描述)
decorator->add_price = 2.0f;
strncpy(decorator->add_desc, "糖", MAX_DESC);
return (CoffeeComponent*)decorator;
}
// -------------------------- 测试代码(客户端) --------------------------
// 客户端:仅依赖抽象组件接口,无需区分基础咖啡和装饰器
void client_order(CoffeeComponent* coffee) {
char desc[MAX_DESC] = {0};
coffee->GetDesc(coffee, desc);
printf("订单:%s,价格:%.1f元\n", desc, coffee->GetPrice(coffee));
}
int main() {
// 1. 点一杯基础美式咖啡(无装饰)
CoffeeComponent* americano = create_americano();
printf("=== 基础订单 ===\n");
client_order(americano);
// 2. 美式 + 牛奶(装饰一次)
CoffeeComponent* coffee_with_milk = create_milk_decorator(americano);
printf("\n=== 装饰一次(加牛奶) ===\n");
client_order(coffee_with_milk);
// 3. 美式 + 牛奶 + 糖(嵌套装饰,动态添加多个职责)
CoffeeComponent* coffee_with_milk_sugar = create_sugar_decorator(coffee_with_milk);
printf("\n=== 嵌套装饰(加牛奶+糖) ===\n");
client_order(coffee_with_milk_sugar);
// 4. 美式 + 糖(单独装饰)
CoffeeComponent* coffee_with_sugar = create_sugar_decorator(create_americano());
printf("\n=== 单独装饰(加糖) ===\n");
client_order(coffee_with_sugar);
// 5. 资源释放(递归销毁,避免内存泄漏)
coffee_with_milk_sugar->Destroy(coffee_with_milk_sugar);
coffee_with_sugar->Destroy(coffee_with_sugar);
return 0;
}
C++语言实现
同 C 语言:咖啡订单系统(抽象组件 Coffee、具体组件 Americano、抽象装饰器 CoffeeDecorator、具体装饰器 Milk/Sugar),支持动态组合装饰器。通过 “抽象基类 + 纯虚函数” 定义统一接口,抽象装饰器继承抽象组件并持有其智能指针(组合关系),代码更简洁、类型更安全。
关键要点
1.接口统一:抽象组件 Coffee 定义纯虚函数 GetDesc/GetPrice,抽象装饰器 CoffeeDecorator 继承 Coffee 并持有其指针,确保装饰器与被装饰对象接口一致。
2.多态核心:客户端通过 Coffee 智能指针调用方法,实际执行子类(Americano/Milk/Sugar)的实现,无需区分组件类型。
3.组合 + 转发:抽象装饰器 CoffeeDecorator 持有 std::shared_ptr,GetDesc/GetPrice 转发调用被装饰对象的方法;具体装饰器重写这两个方法,在转发基础上添加额外逻辑。
4.动态扩展:客户端可通过嵌套 std::make_shared 组合任意多个装饰器(如 Milk(Sugar(Americano()))),无需修改原类代码,符合开闭原则。
5.内存安全:智能指针 std::shared_ptr 自动管理对象生命周期,递归销毁嵌套的装饰器和基础组件,避免内存泄漏;虚析构函数确保子类析构被正确调用。
6.扩展灵活:新增配料(如 “奶泡”)时,只需新增 Foam 类继承 CoffeeDecorator 并实现 GetDesc/GetPrice,客户端可直接使用,无需修改现有代码。
#include <iostream>
#include <string>
#include <memory> // 智能指针(自动管理内存)
// -------------------------- 1. 抽象组件(Component):咖啡抽象基类 --------------------------
class Coffee {
public:
virtual ~Coffee() = default; // 虚析构:确保子类析构被调用
// 纯虚函数:统一接口(强制子类实现)
virtual std::string GetDesc() const = 0;
virtual float GetPrice() const = 0;
};
// -------------------------- 2. 具体组件(ConcreteComponent):基础咖啡(美式) --------------------------
class Americano : public Coffee {
public:
std::string GetDesc() const override {
return "美式咖啡";
}
float GetPrice() const override {
return 15.0f; // 基础价格
}
};
// -------------------------- 3. 抽象装饰器(Decorator):咖啡装饰器基类 --------------------------
class CoffeeDecorator : public Coffee { // 继承抽象组件,确保接口一致
public:
// 构造函数:传入被装饰的咖啡组件(组合关系)
explicit CoffeeDecorator(std::shared_ptr<Coffee> coffee) : coffee_(std::move(coffee)) {}
// 转发调用被装饰组件的接口(子类可重写扩展)
std::string GetDesc() const override {
return coffee_->GetDesc();
}
float GetPrice() const override {
return coffee_->GetPrice();
}
protected:
std::shared_ptr<Coffee> coffee_; // 持有被装饰组件(智能指针自动管理内存)
};
// -------------------------- 4. 具体装饰器(ConcreteDecorator):加牛奶 --------------------------
class Milk : public CoffeeDecorator {
public:
explicit Milk(std::shared_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
// 扩展描述:基础描述 + 牛奶
std::string GetDesc() const override {
return coffee_->GetDesc() + " + 牛奶";
}
// 扩展价格:基础价格 + 3元
float GetPrice() const override {
return coffee_->GetPrice() + 3.0f;
}
};
// -------------------------- 5. 具体装饰器(ConcreteDecorator):加糖 --------------------------
class Sugar : public CoffeeDecorator {
public:
explicit Sugar(std::shared_ptr<Coffee> coffee) : CoffeeDecorator(std::move(coffee)) {}
// 扩展描述:基础描述 + 糖
std::string GetDesc() const override {
return coffee_->GetDesc() + " + 糖";
}
// 扩展价格:基础价格 + 2元
float GetPrice() const override {
return coffee_->GetPrice() + 2.0f;
}
};
// -------------------------- 测试代码(客户端) --------------------------
// 客户端:仅依赖抽象组件(Coffee),无需区分基础咖啡和装饰器
void ClientOrder(const std::shared_ptr<Coffee>& coffee) {
std::cout << "订单:" << coffee->GetDesc() << ",价格:" << coffee->GetPrice() << "元" << std::endl;
}
int main() {
// 1. 基础订单:美式咖啡(无装饰)
std::shared_ptr<Coffee> americano = std::make_shared<Americano>();
std::cout << "=== 基础订单 ===" << std::endl;
ClientOrder(americano);
// 2. 装饰一次:美式 + 牛奶
std::shared_ptr<Coffee> coffee_with_milk = std::make_shared<Milk>(americano);
std::cout << "\n=== 装饰一次(加牛奶) ===" << std::endl;
ClientOrder(coffee_with_milk);
// 3. 嵌套装饰:美式 + 牛奶 + 糖(动态组合多个职责)
std::shared_ptr<Coffee> coffee_with_milk_sugar = std::make_shared<Sugar>(coffee_with_milk);
std::cout << "\n=== 嵌套装饰(加牛奶+糖) ===" << std::endl;
ClientOrder(coffee_with_milk_sugar);
// 4. 单独装饰:美式 + 糖
std::shared_ptr<Coffee> coffee_with_sugar = std::make_shared<Sugar>(std::make_shared<Americano>());
std::cout << "\n=== 单独装饰(加糖) ===" << std::endl;
ClientOrder(coffee_with_sugar);
return 0; // 智能指针自动销毁所有对象,无需手动释放
}
装饰模式核心总结(C vs C++)

设计原则
1.组合优于继承:装饰器通过组合持有组件,而非继承,降低耦合;
2.开闭原则:新增职责只需新增装饰器,无需修改原组件和现有装饰器;
3.接口一致:装饰器与被装饰对象实现同一接口,确保客户端透明操作。

被折叠的 条评论
为什么被折叠?



