1.简介
装饰者模式(Decorator Pattern)是一种结构型设计模式,它允许向对象动态地添加新的功能。这种模式通过创建一个装饰类来包装原有的类,可以在不修改原类的基础上给类添加新的职责。
适用场景
- 当需要扩展一个类的功能或者给一个类添加附加职责时,装饰者模式提供了一种比继承更加灵活的方式。
- 当不能采用生成子类的方法进行扩充时,一种情况是系统中存在大量的独立扩展,为支持每一种组合将产生大量的子类,使得子类数目呈爆炸性增长。
- 另一种情况可能是因为类定义被隐藏,或类定义经过精心设计,如被做成最终类(final class)等方式,不能被继承。
2.通俗讲解
想象一下,你经营着一家咖啡店,基本的产品是“咖啡”,但是顾客还可以选择添加不同的配料(比如牛奶、糖等),这些配料可以自由组合。我们可以通过装饰者模式来实现这样的功能。
3.实战
- 定义抽象组件接口:这是所有实体和装饰者的共同接口。
- 创建具体组件:实现抽象组件接口,代表具体的基本功能。
- 创建抽象装饰器:实现抽象组件接口,并持有具体组件的实例。
- 创建具体装饰器:继承自抽象装饰器,负责添加新行为。
3.1.代码
#include <stdio.h>
#include <stdlib.h>
// 定义抽象组件接口
typedef struct Component {
int cost;
} Component;
// 定义抽象装饰器
typedef struct Decorator {
Component *component;
} Decorator;
// 具体组件: 咖啡
typedef struct Coffee {
Component base;
} Coffee;
// 具体装饰器: 牛奶
typedef struct MilkDecorator {
Decorator base;
} MilkDecorator;
// 具体装饰器: 糖
typedef struct SugarDecorator {
Decorator base;
} SugarDecorator;
// 初始化咖啡
Coffee* createCoffee() {
Coffee *coffee = (Coffee *)malloc(sizeof(Coffee));
coffee->base.cost = 10; // 假设基础咖啡的价格是10元
return coffee;
}
// 初始化牛奶装饰器
MilkDecorator* createMilkDecorator(Component *coffee) {
MilkDecorator *milkDecorator = (MilkDecorator *)malloc(sizeof(MilkDecorator));
milkDecorator->base.component = coffee;
milkDecorator->base.component->cost += 5; // 添加牛奶后价格增加5元
return milkDecorator;
}
// 初始化糖装饰器
SugarDecorator* createSugarDecorator(Component *coffee) {
SugarDecorator *sugarDecorator = (SugarDecorator *)malloc(sizeof(SugarDecorator));
sugarDecorator->base.component = coffee;
sugarDecorator->base.component->cost += 2; // 添加糖后价格增加2元
return sugarDecorator;
}
int main() {
Coffee *coffee = createCoffee();
printf("Basic Coffee Cost: %d\n", coffee->base.cost);
MilkDecorator *milkCoffee = createMilkDecorator((Component *)coffee);
printf("Coffee with Milk Cost: %d\n", milkCoffee->base.component->cost);
SugarDecorator *sugarCoffee = createSugarDecorator((Component *)coffee);
printf("Coffee with Sugar Cost: %d\n", sugarCoffee->base.component->cost);
SugarDecorator *milkSugarCoffee = createSugarDecorator((Component *)milkCoffee);
printf("Coffee with Milk and Sugar Cost: %d\n", milkSugarCoffee->base.component->cost);
free(coffee);
free(milkCoffee);
free(sugarCoffee);
free(milkSugarCoffee);
return 0;
}
3.2.代码解析
- 创建一个基本的咖啡对象,其成本为10元。
- 创建一个带有牛奶的咖啡对象,其成本为基本咖啡成本加上牛奶的成本5元。
- 创建一个带有糖的咖啡对象,其成本为基本咖啡成本加上糖的成本2元。
- 创建一个既带有牛奶又带有糖的咖啡对象,其成本为带有牛奶的咖啡成本再加上糖的成本2元。
通过装饰者模式,我们能够在不改变原始咖啡对象的情况下,为其动态地添加新的特性(即不同的配料)。这种方式提供了很好的灵活性,并且避免了使用多个继承带来的复杂性和维护上的困难。
3.3.代码运行
Basic Coffee Cost: 10
Coffee with Milk Cost: 15
Coffee with Sugar Cost: 12
Coffee with Milk and Sugar Cost: 17