设计模式详解:7大原则和23种设计模式
目录
设计模式7大原则
1. 单一职责原则(Single Responsibility Principle, SRP)
通俗解释: 一个类只做一件事,就像一个人只负责一个岗位。
生活例子:
- ❌ 不好的设计:一个员工既要做会计,又要做销售,还要做客服
- ✅ 好的设计:会计专门做账,销售专门卖货,客服专门处理客户问题
为什么重要: 如果一个人身兼数职,一旦某个职责出问题,其他职责也会受影响。代码也一样,职责单一,修改时不会影响其他功能。
2. 开闭原则(Open-Closed Principle, OCP)
通俗解释: 对扩展开放,对修改关闭。就像手机可以安装新APP(扩展),但不需要拆开手机修改硬件(关闭修改)。
生活例子:
- 手机系统:可以安装新APP(扩展),但不需要修改系统内核(关闭修改)
- 插座:可以插各种电器(扩展),但插座本身不需要改动(关闭修改)
为什么重要: 当需要添加新功能时,不需要修改现有代码,只需要添加新代码,降低了引入bug的风险。
3. 里氏替换原则(Liskov Substitution Principle, LSP)
通俗解释: 子类可以替换父类,而且替换后程序还能正常工作。就像"苹果是水果"一样,任何需要水果的地方,都可以用苹果。
生活例子:
- 如果"汽车"是"交通工具"的子类,那么任何需要交通工具的地方,都可以用汽车
- 如果"金毛"是"狗"的子类,那么任何需要狗的地方,都可以用金毛
为什么重要: 保证继承关系的正确性,子类不能破坏父类的功能。
4. 依赖倒置原则(Dependency Inversion Principle, DIP)
通俗解释: 高层模块不应该依赖低层模块,两者都应该依赖抽象。就像看电视,你依赖的是"电视接口",而不是具体的"某品牌电视"。
生活例子:
- 充电:手机依赖的是"USB接口标准",而不是具体的"某品牌充电器"
- 开车:司机依赖的是"方向盘、油门、刹车"这些抽象概念,而不是具体的"某品牌汽车"
为什么重要: 降低模块间的耦合,提高代码的可维护性和可扩展性。
5. 接口隔离原则(Interface Segregation Principle, ISP)
通俗解释: 不应该强迫客户端依赖它不需要的接口。就像餐厅菜单,不应该把"素食菜单"和"肉食菜单"混在一起。
生活例子:
- ❌ 不好的设计:一个接口包含"飞行"、"游泳"、"跑步",但鸭子只需要"飞行"和"游泳"
- ✅ 好的设计:分别定义"飞行接口"、"游泳接口"、"跑步接口",需要什么实现什么
为什么重要: 避免接口臃肿,让实现类只实现它需要的功能。
6. 迪米特法则(Law of Demeter, LoD)
通俗解释: 只和直接朋友交流,不和陌生人说话。就像你买东西,直接找售货员,而不是找售货员的老板的老板。
生活例子:
- ❌ 不好的设计:A类通过B类获取C类,再通过C类获取D类
- ✅ 好的设计:A类直接和B类交流,B类负责和C类、D类交流
为什么重要: 降低类之间的耦合度,提高模块的相对独立性。
7. 合成复用原则(Composite Reuse Principle, CRP)
通俗解释: 优先使用组合/聚合,而不是继承。就像组装电脑,用现成的零件组合,而不是自己造一个全新的电脑。
生活例子:
- ❌ 不好的设计:为了用"轮子"功能,继承"汽车"类(太重了)
- ✅ 好的设计:把"轮子"作为"自行车"的一个组成部分(组合)
为什么重要: 继承会带来强耦合,组合更灵活,可以动态改变。
创建型模式(5个)
创建型模式关注如何创建对象,让创建过程更灵活、更解耦。
1. 单例模式(Singleton Pattern)
通俗解释: 确保一个类只有一个实例,就像一个国家只有一个总统。
生活例子:
- 打印机:一个办公室通常只有一台打印机,大家共用
- 数据库连接:一个应用通常只需要一个数据库连接池
适用场景:
- 需要全局唯一实例的场景
- 需要控制资源访问的场景
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
// 单例结构体
typedef struct {
int value;
} Singleton;
// 静态变量,存储唯一实例
static Singleton* instance = NULL;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* 获取单例实例
* 使用双重检查锁定(Double-Check Locking)确保线程安全
*/
Singleton* getSingleton() {
// 第一次检查:如果实例已存在,直接返回(避免每次都加锁)
if (instance == NULL) {
// 加锁,确保多线程环境下只有一个线程能创建实例
pthread_mutex_lock(&mutex);
// 第二次检查:再次确认实例是否已创建
// 因为可能另一个线程已经创建了实例
if (instance == NULL) {
// 创建唯一实例
instance = (Singleton*)malloc(sizeof(Singleton));
instance->value = 0;
printf("创建单例实例\n");
}
// 释放锁
pthread_mutex_unlock(&mutex);
}
return instance;
}
/**
* 设置单例的值
*/
void setSingletonValue(int value) {
Singleton* s = getSingleton();
s->value = value;
}
/**
* 获取单例的值
*/
int getSingletonValue() {
Singleton* s = getSingleton();
return s->value;
}
// 测试代码
int main() {
// 获取单例实例
Singleton* s1 = getSingleton();
setSingletonValue(100);
printf("s1的值: %d\n", getSingletonValue());
// 再次获取,应该是同一个实例
Singleton* s2 = getSingleton();
printf("s2的值: %d\n", getSingletonValue());
// 修改s2的值
setSingletonValue(200);
printf("s1的值: %d\n", getSingletonValue()); // s1的值也变了,说明是同一个实例
return 0;
}
编译运行:
bash
gcc singleton.c -o singleton -lpthread
./singleton
2. 工厂方法模式(Factory Method Pattern)
通俗解释: 定义一个创建对象的接口,让子类决定实例化哪个类。就像工厂生产产品,不同工厂生产不同产品。
生活例子:
- 汽车工厂:有"轿车工厂"、"SUV工厂",都继承自"汽车工厂"
- 手机工厂:有"苹果工厂"、"华为工厂",都继承自"手机工厂"
适用场景:
- 需要创建对象,但不确定具体类型
- 需要扩展新的产品类型
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
// ========== 产品接口 ==========
// 定义产品的抽象接口
typedef struct {
void (*use)(void* self); // 使用产品的函数指针
char name[50]; // 产品名称
} Product;
// 产品使用函数(虚函数)
void product_use(void* self) {
Product* p = (Product*)self;
printf("使用产品: %s\n", p->name);
}
// ========== 具体产品A ==========
typedef struct {
Product base; // 继承Product
int typeA_data;
} ProductA;
void productA_use(void* self) {
ProductA* pa = (ProductA*)self;
printf("使用产品A: %s (类型A数据: %d)\n", pa->base.name, pa->typeA_data);
}
ProductA* createProductA() {
ProductA* pa = (ProductA*)malloc(sizeof(ProductA));
pa->base.use = productA_use;
pa->base.name[0] = '\0';
sprintf(pa->base.name, "产品A");
pa->typeA_data = 100;
return pa;
}
// ========== 具体产品B ==========
typedef struct {
Product base; // 继承Product
char typeB_data[50];
} ProductB;
void productB_use(void* self) {
ProductB* pb = (ProductB*)self;
printf("使用产品B: %s (类型B数据: %s)\n", pb->base.name, pb->typeB_data);
}
ProductB* createProductB() {
ProductB* pb = (ProductB*)malloc(sizeof(ProductB));
pb->base.use = productB_use;
pb->base.name[0] = '\0';
sprintf(pb->base.name, "产品B");
sprintf(pb->typeB_data, "类型B的数据");
return pb;
}
// ========== 工厂接口 ==========
// 定义工厂的抽象接口
typedef struct {
Product* (*createProduct)(void* self); // 创建产品的函数指针
} Factory;
// ========== 具体工厂A ==========
typedef struct {
Factory base; // 继承Factory
} FactoryA;
Product* factoryA_createProduct(void* self) {
printf("工厂A创建产品A\n");
return (Product*)createProductA();
}
FactoryA* createFactoryA() {
FactoryA* fa = (FactoryA*)malloc(sizeof(FactoryA));
fa->base.createProduct = factoryA_createProduct;
return fa;
}
// ========== 具体工厂B ==========
typedef struct {
Factory base; // 继承Factory
} FactoryB;
Product* factoryB_createProduct(void* self) {
printf("工厂B创建产品B\n");
return (Product*)createProductB();
}
FactoryB* createFactoryB() {
FactoryB* fb = (FactoryB*)malloc(sizeof(FactoryB));
fb->base.createProduct = factoryB_createProduct;
return fb;
}
// ========== 测试代码 ==========
int main() {
// 使用工厂A创建产品
FactoryA* factoryA = createFactoryA();
Product* product1 = factoryA->base.createProduct(factoryA);
product1->use(product1);
// 使用工厂B创建产品
FactoryB* factoryB = createFactoryB();
Product* product2 = factoryB->base.createProduct(factoryB);
product2->use(product2);
// 释放内存
free(product1);
free(product2);
free(factoryA);
free(factoryB);
return 0;
}
编译运行:
bash
gcc factory_method.c -o factory_method
./factory_method
3. 抽象工厂模式(Abstract Factory Pattern)
通俗解释: 提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。就像家具工厂,可以生产"现代风格"或"古典风格"的整套家具。
生活例子:
- 家具工厂:有"现代风格工厂"(生产现代沙发、现代桌子)和"古典风格工厂"(生产古典沙发、古典桌子)
- UI主题:有"深色主题工厂"和"浅色主题工厂",分别生产深色/浅色的按钮、窗口等
适用场景:
- 需要创建一系列相关对象
- 需要保证产品之间的兼容性
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 产品接口:按钮 ==========
typedef struct {
void (*render)(void* self);
char name[50];
} Button;
void button_render(void* self) {
Button* b = (Button*)self;
printf("渲染按钮: %s\n", b->name);
}
// ========== 产品接口:窗口 ==========
typedef struct {
void (*render)(void* self);
char name[50];
} Window;
void window_render(void* self) {
Window* w = (Window*)self;
printf("渲染窗口: %s\n", w->name);
}
// ========== 具体产品:现代风格按钮 ==========
typedef struct {
Button base;
} ModernButton;
void modernButton_render(void* self) {
ModernButton* mb = (ModernButton*)self;
printf("渲染现代风格按钮: %s (简洁、扁平化)\n", mb->base.name);
}
ModernButton* createModernButton() {
ModernButton* mb = (ModernButton*)malloc(sizeof(ModernButton));
mb->base.render = modernButton_render;
strcpy(mb->base.name, "现代按钮");
return mb;
}
// ========== 具体产品:现代风格窗口 ==========
typedef struct {
Window base;
} ModernWindow;
void modernWindow_render(void* self) {
ModernWindow* mw = (ModernWindow*)self;
printf("渲染现代风格窗口: %s (大边框、圆角)\n", mw->base.name);
}
ModernWindow* createModernWindow() {
ModernWindow* mw = (ModernWindow*)malloc(sizeof(ModernWindow));
mw->base.render = modernWindow_render;
strcpy(mw->base.name, "现代窗口");
return mw;
}
// ========== 具体产品:古典风格按钮 ==========
typedef struct {
Button base;
} ClassicButton;
void classicButton_render(void* self) {
ClassicButton* cb = (ClassicButton*)self;
printf("渲染古典风格按钮: %s (华丽、装饰性强)\n", cb->base.name);
}
ClassicButton* createClassicButton() {
ClassicButton* cb = (ClassicButton*)malloc(sizeof(ClassicButton));
cb->base.render = classicButton_render;
strcpy(cb->base.name, "古典按钮");
return cb;
}
// ========== 具体产品:古典风格窗口 ==========
typedef struct {
Window base;
} ClassicWindow;
void classicWindow_render(void* self) {
ClassicWindow* cw = (ClassicWindow*)self;
printf("渲染古典风格窗口: %s (小边框、雕花装饰)\n", cw->base.name);
}
ClassicWindow* createClassicWindow() {
ClassicWindow* cw = (ClassicWindow*)malloc(sizeof(ClassicWindow));
cw->base.render = classicWindow_render;
strcpy(cw->base.name, "古典窗口");
return cw;
}
// ========== 抽象工厂接口 ==========
typedef struct {
Button* (*createButton)(void* self);
Window* (*createWindow)(void* self);
} GUIFactory;
// ========== 具体工厂:现代风格工厂 ==========
typedef struct {
GUIFactory base;
} ModernFactory;
Button* modernFactory_createButton(void* self) {
printf("现代工厂创建现代按钮\n");
return (Button*)createModernButton();
}
Window* modernFactory_createWindow(void* self) {
printf("现代工厂创建现代窗口\n");
return (Window*)createModernWindow();
}
ModernFactory* createModernFactory() {
ModernFactory* mf = (ModernFactory*)malloc(sizeof(ModernFactory));
mf->base.createButton = modernFactory_createButton;
mf->base.createWindow = modernFactory_createWindow;
return mf;
}
// ========== 具体工厂:古典风格工厂 ==========
typedef struct {
GUIFactory base;
} ClassicFactory;
Button* classicFactory_createButton(void* self) {
printf("古典工厂创建古典按钮\n");
return (Button*)createClassicButton();
}
Window* classicFactory_createWindow(void* self) {
printf("古典工厂创建古典窗口\n");
return (Window*)createClassicWindow();
}
ClassicFactory* createClassicFactory() {
ClassicFactory* cf = (ClassicFactory*)malloc(sizeof(ClassicFactory));
cf->base.createButton = classicFactory_createButton;
cf->base.createWindow = classicFactory_createWindow;
return cf;
}
// ========== 客户端代码 ==========
void createUI(GUIFactory* factory) {
printf("\n=== 创建UI界面 ===\n");
Button* button = factory->createButton(factory);
Window* window = factory->createWindow(factory);
printf("\n=== 渲染UI ===\n");
button->render(button);
window->render(window);
free(button);
free(window);
}
int main() {
// 使用现代风格工厂
ModernFactory* modernFactory = createModernFactory();
createUI((GUIFactory*)modernFactory);
printf("\n");
// 使用古典风格工厂
ClassicFactory* classicFactory = createClassicFactory();
createUI((GUIFactory*)classicFactory);
free(modernFactory);
free(classicFactory);
return 0;
}
编译运行:
bash
gcc abstract_factory.c -o abstract_factory
./abstract_factory
4. 建造者模式(Builder Pattern)
通俗解释: 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。就像盖房子,有设计师、施工队,一步步建造。
生活例子:
- 盖房子:先打地基,再建框架,再装修,最后验收
- 点餐:选择主食、配菜、饮料、甜点,最后组成套餐
适用场景:
- 需要创建复杂对象
- 创建过程需要多个步骤
- 需要不同的表示形式
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 产品:房子 ==========
typedef struct {
char foundation[50]; // 地基
char walls[50]; // 墙壁
char roof[50]; // 屋顶
char interior[50]; // 内饰
} House;
void printHouse(House* house) {
printf("=== 房子信息 ===\n");
printf("地基: %s\n", house->foundation);
printf("墙壁: %s\n", house->walls);
printf("屋顶: %s\n", house->roof);
printf("内饰: %s\n", house->interior);
printf("================\n");
}
// ========== 建造者接口 ==========
typedef struct {
void (*buildFoundation)(void* self, const char* type);
void (*buildWalls)(void* self, const char* type);
void (*buildRoof)(void* self, const char* type);
void (*buildInterior)(void* self, const char* type);
House* (*getHouse)(void* self);
} HouseBuilder;
// ========== 具体建造者:普通房子建造者 ==========
typedef struct {
HouseBuilder base;
House* house;
} NormalHouseBuilder;
void normalBuilder_buildFoundation(void* self, const char* type) {
NormalHouseBuilder* builder = (NormalHouseBuilder*)self;
strcpy(builder->house->foundation, type);
printf("建造普通房子的地基: %s\n", type);
}
void normalBuilder_buildWalls(void* self, const char* type) {
NormalHouseBuilder* builder = (NormalHouseBuilder*)self;
strcpy(builder->house->walls, type);
printf("建造普通房子的墙壁: %s\n", type);
}
void normalBuilder_buildRoof(void* self, const char* type) {
NormalHouseBuilder* builder = (NormalHouseBuilder*)self;
strcpy(builder->house->roof, type);
printf("建造普通房子的屋顶: %s\n", type);
}
void normalBuilder_buildInterior(void* self, const char* type) {
NormalHouseBuilder* builder = (NormalHouseBuilder*)self;
strcpy(builder->house->interior, type);
printf("建造普通房子的内饰: %s\n", type);
}
House* normalBuilder_getHouse(void* self) {
NormalHouseBuilder* builder = (NormalHouseBuilder*)self;
return builder->house;
}
NormalHouseBuilder* createNormalHouseBuilder() {
NormalHouseBuilder* builder = (NormalHouseBuilder*)malloc(sizeof(NormalHouseBuilder));
builder->house = (House*)malloc(sizeof(House));
builder->base.buildFoundation = normalBuilder_buildFoundation;
builder->base.buildWalls = normalBuilder_buildWalls;
builder->base.buildRoof = normalBuilder_buildRoof;
builder->base.buildInterior = normalBuilder_buildInterior;
builder->base.getHouse = normalBuilder_getHouse;
return builder;
}
// ========== 具体建造者:豪华房子建造者 ==========
typedef struct {
HouseBuilder base;
House* house;
} LuxuryHouseBuilder;
void luxuryBuilder_buildFoundation(void* self, const char* type) {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)self;
char luxury_type[100];
sprintf(luxury_type, "豪华%s", type);
strcpy(builder->house->foundation, luxury_type);
printf("建造豪华房子的地基: %s\n", luxury_type);
}
void luxuryBuilder_buildWalls(void* self, const char* type) {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)self;
char luxury_type[100];
sprintf(luxury_type, "豪华%s", type);
strcpy(builder->house->walls, luxury_type);
printf("建造豪华房子的墙壁: %s\n", luxury_type);
}
void luxuryBuilder_buildRoof(void* self, const char* type) {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)self;
char luxury_type[100];
sprintf(luxury_type, "豪华%s", type);
strcpy(builder->house->roof, luxury_type);
printf("建造豪华房子的屋顶: %s\n", luxury_type);
}
void luxuryBuilder_buildInterior(void* self, const char* type) {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)self;
char luxury_type[100];
sprintf(luxury_type, "豪华%s", type);
strcpy(builder->house->interior, luxury_type);
printf("建造豪华房子的内饰: %s\n", luxury_type);
}
House* luxuryBuilder_getHouse(void* self) {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)self;
return builder->house;
}
LuxuryHouseBuilder* createLuxuryHouseBuilder() {
LuxuryHouseBuilder* builder = (LuxuryHouseBuilder*)malloc(sizeof(LuxuryHouseBuilder));
builder->house = (House*)malloc(sizeof(House));
builder->base.buildFoundation = luxuryBuilder_buildFoundation;
builder->base.buildWalls = luxuryBuilder_buildWalls;
builder->base.buildRoof = luxuryBuilder_buildRoof;
builder->base.buildInterior = luxuryBuilder_buildInterior;
builder->base.getHouse = luxuryBuilder_getHouse;
return builder;
}
// ========== 导演类:负责建造流程 ==========
typedef struct {
HouseBuilder* builder;
} Director;
void director_construct(Director* director) {
printf("\n=== 开始建造房子 ===\n");
// 按照固定流程建造房子
director->builder->buildFoundation(director->builder, "混凝土");
director->builder->buildWalls(director->builder, "砖墙");
director->builder->buildRoof(director->builder, "瓦片");
director->builder->buildInterior(director->builder, "简装");
printf("=== 房子建造完成 ===\n\n");
}
Director* createDirector(HouseBuilder* builder) {
Director* director = (Director*)malloc(sizeof(Director));
director->builder = builder;
return director;
}
int main() {
// 建造普通房子
NormalHouseBuilder* normalBuilder = createNormalHouseBuilder();
Director* director1 = createDirector((HouseBuilder*)normalBuilder);
director_construct(director1);
House* normalHouse = normalBuilder->base.getHouse(normalBuilder);
printHouse(normalHouse);
// 建造豪华房子
LuxuryHouseBuilder* luxuryBuilder = createLuxuryHouseBuilder();
Director* director2 = createDirector((HouseBuilder*)luxuryBuilder);
director_construct(director2);
House* luxuryHouse = luxuryBuilder->base.getHouse(luxuryBuilder);
printHouse(luxuryHouse);
// 释放内存
free(normalHouse);
free(luxuryHouse);
free(normalBuilder);
free(luxuryBuilder);
free(director1);
free(director2);
return 0;
}
编译运行:
bash
gcc builder.c -o builder
./builder
5. 原型模式(Prototype Pattern)
通俗解释: 通过复制现有实例来创建新实例,而不是新建。就像复印机,可以快速复制文档。
生活例子:
- 复印机:复制一份文档
- 克隆:克隆羊多莉
- 模板:用模板快速创建相似对象
适用场景:
- 创建对象成本高(如需要大量计算或数据库查询)
- 需要创建相似对象
- 需要动态配置对象
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 原型接口 ==========
typedef struct {
void* (*clone)(void* self); // 克隆函数
void (*display)(void* self); // 显示函数
char name[50];
int id;
} Prototype;
// ========== 具体原型:简历 ==========
typedef struct {
Prototype base;
char* workExperience; // 工作经验
int age;
} Resume;
// 克隆函数:深拷贝
void* resume_clone(void* self) {
Resume* original = (Resume*)self;
Resume* copy = (Resume*)malloc(sizeof(Resume));
// 复制基本信息
copy->base.clone = original->base.clone;
copy->base.display = original->base.display;
strcpy(copy->base.name, original->base.name);
copy->base.id = original->base.id + 1000; // 新ID
// 深拷贝工作经验(字符串)
if (original->workExperience) {
int len = strlen(original->workExperience);
copy->workExperience = (char*)malloc(len + 1);
strcpy(copy->workExperience, original->workExperience);
} else {
copy->workExperience = NULL;
}
copy->age = original->age;
printf("克隆简历: %s (新ID: %d)\n", copy->base.name, copy->base.id);
return copy;
}
// 显示函数
void resume_display(void* self) {
Resume* r = (Resume*)self;
printf("=== 简历信息 ===\n");
printf("姓名: %s\n", r->base.name);
printf("ID: %d\n", r->base.id);
printf("年龄: %d\n", r->age);
printf("工作经验: %s\n", r->workExperience ? r->workExperience : "无");
printf("===============\n");
}
// 创建简历原型
Resume* createResume(const char* name, int age, const char* workExp) {
Resume* r = (Resume*)malloc(sizeof(Resume));
r->base.clone = resume_clone;
r->base.display = resume_display;
strcpy(r->base.name, name);
r->base.id = 1001;
r->age = age;
if (workExp) {
int len = strlen(workExp);
r->workExperience = (char*)malloc(len + 1);
strcpy(r->workExperience, workExp);
} else {
r->workExperience = NULL;
}
return r;
}
// 释放简历内存
void freeResume(Resume* r) {
if (r) {
if (r->workExperience) {
free(r->workExperience);
}
free(r);
}
}
// ========== 原型管理器 ==========
typedef struct {
Prototype* prototypes[10]; // 存储原型
int count;
} PrototypeManager;
PrototypeManager* createPrototypeManager() {
PrototypeManager* pm = (PrototypeManager*)malloc(sizeof(PrototypeManager));
pm->count = 0;
return pm;
}
// 注册原型
void registerPrototype(PrototypeManager* pm, Prototype* proto) {
if (pm->count < 10) {
pm->prototypes[pm->count++] = proto;
printf("注册原型: %s\n", proto->name);
}
}
// 获取原型副本
Prototype* getPrototype(PrototypeManager* pm, int index) {
if (index >= 0 && index < pm->count) {
return pm->prototypes[index]->clone(pm->prototypes[index]);
}
return NULL;
}
int main() {
// 创建原始简历
Resume* originalResume = createResume("张三", 25, "5年Java开发经验");
printf("\n=== 原始简历 ===\n");
originalResume->base.display(originalResume);
// 使用原型模式克隆简历
printf("\n=== 克隆简历1 ===\n");
Resume* clonedResume1 = (Resume*)originalResume->base.clone(originalResume);
// 修改克隆后的简历
strcpy(clonedResume1->base.name, "李四");
clonedResume1->age = 28;
clonedResume1->base.display(clonedResume1);
printf("\n=== 克隆简历2 ===\n");
Resume* clonedResume2 = (Resume*)originalResume->base.clone(originalResume);
strcpy(clonedResume2->base.name, "王五");
clonedResume2->age = 30;
if (clonedResume2->workExperience) {
free(clonedResume2->workExperience);
clonedResume2->workExperience = (char*)malloc(50);
strcpy(clonedResume2->workExperience, "3年Python开发经验");
}
clonedResume2->base.display(clonedResume2);
// 使用原型管理器
printf("\n=== 使用原型管理器 ===\n");
PrototypeManager* pm = createPrototypeManager();
registerPrototype(pm, (Prototype*)originalResume);
Resume* clonedResume3 = (Resume*)getPrototype(pm, 0);
clonedResume3->base.display(clonedResume3);
// 释放内存
freeResume(originalResume);
freeResume(clonedResume1);
freeResume(clonedResume2);
freeResume(clonedResume3);
free(pm);
return 0;
}
编译运行:
bash
gcc prototype.c -o prototype
./prototype
总结:创建型模式
创建型模式帮助我们更灵活地创建对象:
- 单例模式:确保只有一个实例
- 工厂方法模式:让子类决定创建什么对象
- 抽象工厂模式:创建一系列相关对象
- 建造者模式:分步骤创建复杂对象
- 原型模式:通过复制创建对象
每种模式都解决了不同的对象创建问题,选择合适的模式可以让代码更清晰、更易维护。
设计模式详解:结构型模式(7个)
结构型模式关注如何组合类和对象,形成更大的结构。
1. 适配器模式(Adapter Pattern)
通俗解释: 让不兼容的接口能够一起工作。就像电源适配器,让不同国家的插头都能用。
生活例子:
- 电源适配器:把220V电压转换成110V,让美国电器在中国能用
- USB转HDMI:让USB接口的设备能连接HDMI显示器
- 翻译器:让说不同语言的人能交流
适用场景:
- 需要使用现有类,但接口不兼容
- 需要统一多个不同接口
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 目标接口:新系统需要的接口 ==========
// 这是客户端期望的接口
typedef struct {
void (*request)(void* self); // 请求函数
} Target;
void target_request(void* self) {
printf("目标接口:处理标准请求\n");
}
// ========== 被适配者:旧系统(不兼容的接口) ==========
// 这是已经存在的类,但接口不兼容
typedef struct {
void (*specificRequest)(void* self); // 特殊请求函数
} Adaptee;
void adaptee_specificRequest(void* self) {
printf("被适配者:处理特殊请求(旧接口)\n");
}
Adaptee* createAdaptee() {
Adaptee* a = (Adaptee*)malloc(sizeof(Adaptee));
a->specificRequest = adaptee_specificRequest;
return a;
}
// ========== 适配器:连接目标接口和被适配者 ==========
// 适配器实现了目标接口,内部使用被适配者
typedef struct {
Target base; // 继承目标接口
Adaptee* adaptee; // 包含被适配者
} Adapter;
void adapter_request(void* self) {
Adapter* adapter = (Adapter*)self;
printf("适配器:将标准请求转换为特殊请求\n");
// 调用被适配者的方法,实现适配
adapter->adaptee->specificRequest(adapter->adaptee);
}
Adapter* createAdapter(Adaptee* adaptee) {
Adapter* adapter = (Adapter*)malloc(sizeof(Adapter));
adapter->base.request = adapter_request;
adapter->adaptee = adaptee;
return adapter;
}
// ========== 客户端代码 ==========
void clientCode(Target* target) {
printf("客户端:调用目标接口\n");
target->request(target);
}
int main() {
printf("=== 适配器模式演示 ===\n\n");
// 创建被适配者(旧系统)
Adaptee* adaptee = createAdaptee();
// 创建适配器,将旧系统适配到新接口
Adapter* adapter = createAdapter(adaptee);
// 客户端使用目标接口(新接口)
// 适配器让旧系统看起来像新接口
clientCode((Target*)adapter);
// 释放内存
free(adaptee);
free(adapter);
return 0;
}
编译运行:
bash
gcc adapter.c -o adapter
./adapter
2. 桥接模式(Bridge Pattern)
通俗解释: 将抽象和实现分离,使它们可以独立变化。就像遥控器和电视,遥控器(抽象)可以控制不同品牌的电视(实现)。
生活例子:
- 遥控器和电视:遥控器是抽象,不同品牌电视是实现
- 画笔和颜色:画笔是抽象,不同颜色是实现
- 操作系统和驱动程序:操作系统是抽象,不同硬件驱动是实现
适用场景:
- 需要在运行时切换实现
- 需要避免抽象和实现的绑定
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 实现接口:颜色(实现部分) ==========
// 这是实现部分的抽象
typedef struct {
void (*applyColor)(void* self); // 应用颜色
char colorName[50];
} Color;
void color_applyColor(void* self) {
Color* c = (Color*)self;
printf("应用颜色: %s\n", c->colorName);
}
// ========== 具体实现:红色 ==========
typedef struct {
Color base;
} RedColor;
void redColor_applyColor(void* self) {
RedColor* rc = (RedColor*)self;
printf("应用红色\n");
}
RedColor* createRedColor() {
RedColor* rc = (RedColor*)malloc(sizeof(RedColor));
rc->base.applyColor = redColor_applyColor;
strcpy(rc->base.colorName, "红色");
return rc;
}
// ========== 具体实现:蓝色 ==========
typedef struct {
Color base;
} BlueColor;
void blueColor_applyColor(void* self) {
BlueColor* bc = (BlueColor*)self;
printf("应用蓝色\n");
}
BlueColor* createBlueColor() {
BlueColor* bc = (BlueColor*)malloc(sizeof(BlueColor));
bc->base.applyColor = blueColor_applyColor;
strcpy(bc->base.colorName, "蓝色");
return bc;
}
// ========== 抽象类:形状(抽象部分) ==========
// 这是抽象部分,包含对实现的引用
typedef struct {
Color* color; // 桥接:持有实现部分的引用
void (*draw)(void* self); // 绘制函数
} Shape;
void shape_draw(void* self) {
Shape* s = (Shape*)self;
printf("绘制形状");
if (s->color) {
printf(",使用");
s->color->applyColor(s->color);
}
}
// ========== 具体抽象:圆形 ==========
typedef struct {
Shape base;
} Circle;
void circle_draw(void* self) {
Circle* c = (Circle*)self;
printf("绘制圆形");
if (c->base.color) {
printf(",使用");
c->base.color->applyColor(c->base.color);
}
printf("\n");
}
Circle* createCircle(Color* color) {
Circle* circle = (Circle*)malloc(sizeof(Circle));
circle->base.color = color; // 桥接:设置实现
circle->base.draw = circle_draw;
return circle;
}
// ========== 具体抽象:方形 ==========
typedef struct {
Shape base;
} Square;
void square_draw(void* self) {
Square* s = (Square*)self;
printf("绘制方形");
if (s->base.color) {
printf(",使用");
s->base.color->applyColor(s->base.color);
}
printf("\n");
}
Square* createSquare(Color* color) {
Square* square = (Square*)malloc(sizeof(Square));
square->base.color = color; // 桥接:设置实现
square->base.draw = square_draw;
return square;
}
int main() {
printf("=== 桥接模式演示 ===\n\n");
// 创建实现:红色和蓝色
RedColor* red = createRedColor();
BlueColor* blue = createBlueColor();
// 创建抽象:圆形和方形,并桥接到不同的颜色实现
printf("--- 红色圆形 ---\n");
Circle* redCircle = createCircle((Color*)red);
redCircle->base.draw(redCircle);
printf("\n--- 蓝色圆形 ---\n");
Circle* blueCircle = createCircle((Color*)blue);
blueCircle->base.draw(blueCircle);
printf("\n--- 红色方形 ---\n");
Square* redSquare = createSquare((Color*)red);
redSquare->base.draw(redSquare);
printf("\n--- 蓝色方形 ---\n");
Square* blueSquare = createSquare((Color*)blue);
blueSquare->base.draw(blueSquare);
// 释放内存
free(red);
free(blue);
free(redCircle);
free(blueCircle);
free(redSquare);
free(blueSquare);
return 0;
}
编译运行:
bash
gcc bridge.c -o bridge
./bridge
3. 组合模式(Composite Pattern)
通俗解释: 将对象组合成树形结构,使单个对象和组合对象使用一致。就像文件夹和文件,文件夹可以包含文件,也可以包含其他文件夹。
生活例子:
- 文件系统:文件夹可以包含文件或子文件夹
- 组织结构:部门可以包含员工或子部门
- 菜单系统:菜单可以包含菜单项或子菜单
适用场景:
- 需要表示部分-整体层次结构
- 需要统一处理单个对象和组合对象
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 组件接口 ==========
// 这是组合模式的核心接口,既可以表示叶子节点,也可以表示组合节点
typedef struct Component {
char name[100];
void (*operation)(struct Component* self); // 操作函数
void (*add)(struct Component* self, struct Component* child); // 添加子组件
void (*remove)(struct Component* self, struct Component* child); // 移除子组件
struct Component* (*getChild)(struct Component* self, int index); // 获取子组件
} Component;
// ========== 叶子节点:文件 ==========
// 叶子节点没有子节点
typedef struct {
Component base;
int size; // 文件大小
} File;
void file_operation(Component* self) {
File* f = (File*)self;
printf("文件: %s (大小: %d KB)\n", f->base.name, f->size);
}
void file_add(Component* self, Component* child) {
printf("错误:文件不能添加子组件\n");
}
void file_remove(Component* self, Component* child) {
printf("错误:文件不能移除子组件\n");
}
Component* file_getChild(Component* self, int index) {
return NULL; // 文件没有子节点
}
File* createFile(const char* name, int size) {
File* f = (File*)malloc(sizeof(File));
strcpy(f->base.name, name);
f->size = size;
f->base.operation = file_operation;
f->base.add = file_add;
f->base.remove = file_remove;
f->base.getChild = file_getChild;
return f;
}
// ========== 组合节点:文件夹 ==========
// 组合节点可以包含子组件
typedef struct {
Component base;
Component* children[100]; // 子组件数组
int childCount; // 子组件数量
} Folder;
void folder_operation(Component* self) {
Folder* folder = (Folder*)self;
printf("文件夹: %s (包含 %d 个项目)\n", folder->base.name, folder->childCount);
// 递归操作所有子组件
for (int i = 0; i < folder->childCount; i++) {
printf(" ");
folder->children[i]->operation(folder->children[i]);
}
}
void folder_add(Component* self, Component* child) {
Folder* folder = (Folder*)self;
if (folder->childCount < 100) {
folder->children[folder->childCount++] = child;
printf("添加 %s 到 %s\n", child->name, folder->base.name);
}
}
void folder_remove(Component* self, Component* child) {
Folder* folder = (Folder*)self;
for (int i = 0; i < folder->childCount; i++) {
if (folder->children[i] == child) {
// 移除子组件
for (int j = i; j < folder->childCount - 1; j++) {
folder->children[j] = folder->children[j + 1];
}
folder->childCount--;
printf("从 %s 移除 %s\n", folder->base.name, child->name);
return;
}
}
}
Component* folder_getChild(Component* self, int index) {
Folder* folder = (Folder*)self;
if (index >= 0 && index < folder->childCount) {
return folder->children[index];
}
return NULL;
}
Folder* createFolder(const char* name) {
Folder* folder = (Folder*)malloc(sizeof(Folder));
strcpy(folder->base.name, name);
folder->childCount = 0;
folder->base.operation = folder_operation;
folder->base.add = folder_add;
folder->base.remove = folder_remove;
folder->base.getChild = folder_getChild;
return folder;
}
int main() {
printf("=== 组合模式演示 ===\n\n");
// 创建根文件夹
Folder* root = createFolder("根目录");
// 创建文件
File* file1 = createFile("文档.txt", 10);
File* file2 = createFile("图片.jpg", 500);
// 创建子文件夹
Folder* subFolder = createFolder("子文件夹");
// 创建子文件夹中的文件
File* file3 = createFile("数据.csv", 50);
File* file4 = createFile("报告.pdf", 200);
// 构建树形结构
printf("--- 构建文件系统结构 ---\n");
root->base.add((Component*)root, (Component*)file1);
root->base.add((Component*)root, (Component*)file2);
root->base.add((Component*)root, (Component*)subFolder);
subFolder->base.add((Component*)subFolder, (Component*)file3);
subFolder->base.add((Component*)subFolder, (Component*)file4);
printf("\n--- 遍历文件系统 ---\n");
// 统一操作:无论是文件还是文件夹,都用同样的接口
root->base.operation((Component*)root);
// 释放内存(简化版,实际应该递归释放)
free(file1);
free(file2);
free(file3);
free(file4);
free(subFolder);
free(root);
return 0;
}
编译运行:
bash
gcc composite.c -o composite
./composite
4. 装饰器模式(Decorator Pattern)
通俗解释: 动态地给对象添加新功能,比继承更灵活。就像给手机加保护壳、贴膜、挂件,一层层装饰。
生活例子:
- 手机装饰:手机 + 保护壳 + 贴膜 + 挂件
- 咖啡:咖啡 + 糖 + 牛奶 + 奶油
- 披萨:基础披萨 + 芝士 + 香肠 + 蔬菜
适用场景:
- 需要动态添加功能
- 不想使用继承扩展功能
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 组件接口:咖啡 ==========
typedef struct {
char description[100];
int (*cost)(void* self); // 计算价格
void (*getDescription)(void* self, char* buffer); // 获取描述
} Coffee;
int coffee_cost(void* self) {
return 0;
}
void coffee_getDescription(void* self, char* buffer) {
Coffee* c = (Coffee*)self;
strcpy(buffer, c->description);
}
// ========== 具体组件:基础咖啡 ==========
typedef struct {
Coffee base;
} SimpleCoffee;
int simpleCoffee_cost(void* self) {
return 10; // 基础咖啡10元
}
void simpleCoffee_getDescription(void* self, char* buffer) {
strcpy(buffer, "基础咖啡");
}
SimpleCoffee* createSimpleCoffee() {
SimpleCoffee* sc = (SimpleCoffee*)malloc(sizeof(SimpleCoffee));
strcpy(sc->base.description, "基础咖啡");
sc->base.cost = simpleCoffee_cost;
sc->base.getDescription = simpleCoffee_getDescription;
return sc;
}
// ========== 装饰器基类 ==========
typedef struct {
Coffee base;
Coffee* coffee; // 被装饰的咖啡
} CoffeeDecorator;
// ========== 具体装饰器:加糖 ==========
typedef struct {
CoffeeDecorator base;
} SugarDecorator;
int sugarDecorator_cost(void* self) {
SugarDecorator* sd = (SugarDecorator*)self;
return sd->base.coffee->cost(sd->base.coffee) + 2; // 加2元
}
void sugarDecorator_getDescription(void* self, char* buffer) {
SugarDecorator* sd = (SugarDecorator*)self;
char temp[200];
sd->base.coffee->getDescription(sd->base.coffee, temp);
sprintf(buffer, "%s + 糖", temp);
}
SugarDecorator* createSugarDecorator(Coffee* coffee) {
SugarDecorator* sd = (SugarDecorator*)malloc(sizeof(SugarDecorator));
sd->base.coffee = coffee;
sd->base.cost = sugarDecorator_cost;
sd->base.getDescription = sugarDecorator_getDescription;
return sd;
}
// ========== 具体装饰器:加牛奶 ==========
typedef struct {
CoffeeDecorator base;
} MilkDecorator;
int milkDecorator_cost(void* self) {
MilkDecorator* md = (MilkDecorator*)self;
return md->base.coffee->cost(md->base.coffee) + 3; // 加3元
}
void milkDecorator_getDescription(void* self, char* buffer) {
MilkDecorator* md = (MilkDecorator*)self;
char temp[200];
md->base.coffee->getDescription(md->base.coffee, temp);
sprintf(buffer, "%s + 牛奶", temp);
}
MilkDecorator* createMilkDecorator(Coffee* coffee) {
MilkDecorator* md = (MilkDecorator*)malloc(sizeof(MilkDecorator));
md->base.coffee = coffee;
md->base.cost = milkDecorator_cost;
md->base.getDescription = milkDecorator_getDescription;
return md;
}
// ========== 具体装饰器:加奶油 ==========
typedef struct {
CoffeeDecorator base;
} CreamDecorator;
int creamDecorator_cost(void* self) {
CreamDecorator* cd = (CreamDecorator*)self;
return cd->base.coffee->cost(cd->base.coffee) + 4; // 加4元
}
void creamDecorator_getDescription(void* self, char* buffer) {
CreamDecorator* cd = (CreamDecorator*)self;
char temp[200];
cd->base.coffee->getDescription(cd->base.coffee, temp);
sprintf(buffer, "%s + 奶油", temp);
}
CreamDecorator* createCreamDecorator(Coffee* coffee) {
CreamDecorator* cd = (CreamDecorator*)malloc(sizeof(CreamDecorator));
cd->base.coffee = coffee;
cd->base.cost = creamDecorator_cost;
cd->base.getDescription = creamDecorator_getDescription;
return cd;
}
int main() {
printf("=== 装饰器模式演示 ===\n\n");
// 创建基础咖啡
SimpleCoffee* coffee = createSimpleCoffee();
char desc[200];
coffee->base.getDescription(&coffee->base, desc);
printf("订单1: %s\n", desc);
printf("价格: %d元\n\n", coffee->base.cost(&coffee->base));
// 装饰:加糖
SugarDecorator* coffeeWithSugar = createSugarDecorator((Coffee*)coffee);
coffeeWithSugar->base.getDescription((Coffee*)coffeeWithSugar, desc);
printf("订单2: %s\n", desc);
printf("价格: %d元\n\n", coffeeWithSugar->base.cost((Coffee*)coffeeWithSugar));
// 装饰:加糖 + 牛奶
MilkDecorator* coffeeWithSugarMilk = createMilkDecorator((Coffee*)coffeeWithSugar);
coffeeWithSugarMilk->base.getDescription((Coffee*)coffeeWithSugarMilk, desc);
printf("订单3: %s\n", desc);
printf("价格: %d元\n\n", coffeeWithSugarMilk->base.cost((Coffee*)coffeeWithSugarMilk));
// 装饰:加糖 + 牛奶 + 奶油
CreamDecorator* coffeeWithAll = createCreamDecorator((Coffee*)coffeeWithSugarMilk);
coffeeWithAll->base.getDescription((Coffee*)coffeeWithAll, desc);
printf("订单4: %s\n", desc);
printf("价格: %d元\n\n", coffeeWithAll->base.cost((Coffee*)coffeeWithAll));
// 释放内存(简化版)
free(coffee);
free(coffeeWithSugar);
free(coffeeWithSugarMilk);
free(coffeeWithAll);
return 0;
}
编译运行:
bash
gcc decorator.c -o decorator
./decorator
5. 外观模式(Facade Pattern)
通俗解释: 为复杂子系统提供一个简单接口。就像一键启动电脑,不需要知道CPU、内存、硬盘如何协调工作。
生活例子:
- 一键启动:一键启动电脑,隐藏了复杂的启动过程
- 银行ATM:简单的界面,背后是复杂的银行系统
- 智能家居:一个APP控制所有设备,隐藏了复杂的通信协议
适用场景:
- 需要简化复杂子系统
- 需要解耦客户端和子系统
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 子系统1:CPU ==========
typedef struct {
void (*start)(void);
void (*stop)(void);
} CPU;
void cpu_start(void) {
printf("CPU: 启动\n");
}
void cpu_stop(void) {
printf("CPU: 停止\n");
}
CPU* createCPU() {
CPU* cpu = (CPU*)malloc(sizeof(CPU));
cpu->start = cpu_start;
cpu->stop = cpu_stop;
return cpu;
}
// ========== 子系统2:内存 ==========
typedef struct {
void (*load)(void);
void (*unload)(void);
} Memory;
void memory_load(void) {
printf("内存: 加载数据\n");
}
void memory_unload(void) {
printf("内存: 卸载数据\n");
}
Memory* createMemory() {
Memory* mem = (Memory*)malloc(sizeof(Memory));
mem->load = memory_load;
mem->unload = memory_unload;
return mem;
}
// ========== 子系统3:硬盘 ==========
typedef struct {
void (*read)(void);
void (*write)(void);
} HardDrive;
void hardDrive_read(void) {
printf("硬盘: 读取数据\n");
}
void hardDrive_write(void) {
printf("硬盘: 写入数据\n");
}
HardDrive* createHardDrive() {
HardDrive* hd = (HardDrive*)malloc(sizeof(HardDrive));
hd->read = hardDrive_read;
hd->write = hardDrive_write;
return hd;
}
// ========== 外观类:计算机 ==========
// 外观类封装了子系统的复杂操作,提供简单接口
typedef struct {
CPU* cpu;
Memory* memory;
HardDrive* hardDrive;
void (*startComputer)(void* self);
void (*stopComputer)(void* self);
} Computer;
void computer_startComputer(void* self) {
Computer* comp = (Computer*)self;
printf("=== 启动计算机 ===\n");
comp->cpu->start();
comp->memory->load();
comp->hardDrive->read();
printf("计算机启动完成!\n\n");
}
void computer_stopComputer(void* self) {
Computer* comp = (Computer*)self;
printf("=== 关闭计算机 ===\n");
comp->hardDrive->write();
comp->memory->unload();
comp->cpu->stop();
printf("计算机关闭完成!\n\n");
}
Computer* createComputer() {
Computer* comp = (Computer*)malloc(sizeof(Computer));
comp->cpu = createCPU();
comp->memory = createMemory();
comp->hardDrive = createHardDrive();
comp->startComputer = computer_startComputer;
comp->stopComputer = computer_stopComputer;
return comp;
}
void freeComputer(Computer* comp) {
if (comp) {
free(comp->cpu);
free(comp->memory);
free(comp->hardDrive);
free(comp);
}
}
int main() {
printf("=== 外观模式演示 ===\n\n");
// 创建计算机(外观对象)
Computer* computer = createComputer();
// 客户端只需要调用简单接口,不需要知道子系统细节
printf("--- 用户操作:启动电脑 ---\n");
computer->startComputer(computer);
printf("--- 用户操作:关闭电脑 ---\n");
computer->stopComputer(computer);
// 如果不使用外观模式,客户端需要这样操作(复杂):
printf("--- 不使用外观模式(复杂) ---\n");
CPU* cpu = createCPU();
Memory* mem = createMemory();
HardDrive* hd = createHardDrive();
cpu->start();
mem->load();
hd->read();
hd->write();
mem->unload();
cpu->stop();
// 释放内存
freeComputer(computer);
free(cpu);
free(mem);
free(hd);
return 0;
}
编译运行:
bash
gcc facade.c -o facade
./facade
6. 享元模式(Flyweight Pattern)
通俗解释: 通过共享相同数据来减少内存使用。就像图书馆,多个人可以共享同一本书,而不需要每人买一本。
生活例子:
- 图书馆:多个人共享同一本书
- 字体:多个字符共享同一字体对象
- 游戏:多个敌人共享同一模型和纹理
适用场景:
- 需要创建大量相似对象
- 对象的大部分状态可以共享
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 享元接口:字符 ==========
typedef struct {
char symbol; // 字符(内部状态,可共享)
void (*display)(void* self, int x, int y); // 显示函数
} Character;
// ========== 具体享元:具体字符 ==========
typedef struct {
Character base;
char font[50]; // 字体(内部状态,可共享)
int size; // 大小(内部状态,可共享)
} ConcreteCharacter;
void character_display(void* self, int x, int y) {
ConcreteCharacter* cc = (ConcreteCharacter*)self;
printf("显示字符 '%c' (字体: %s, 大小: %d) 在位置 (%d, %d)\n",
cc->base.symbol, cc->font, cc->size, x, y);
}
ConcreteCharacter* createCharacter(char symbol, const char* font, int size) {
ConcreteCharacter* cc = (ConcreteCharacter*)malloc(sizeof(ConcreteCharacter));
cc->base.symbol = symbol;
strcpy(cc->font, font);
cc->size = size;
cc->base.display = character_display;
return cc;
}
// ========== 享元工厂:管理享元对象 ==========
typedef struct {
ConcreteCharacter* characters[100]; // 享元对象池
int count;
} CharacterFactory;
CharacterFactory* createCharacterFactory() {
CharacterFactory* factory = (CharacterFactory*)malloc(sizeof(CharacterFactory));
factory->count = 0;
return factory;
}
// 获取享元对象(如果不存在则创建)
ConcreteCharacter* getCharacter(CharacterFactory* factory, char symbol, const char* font, int size) {
// 查找是否已存在相同的享元对象
for (int i = 0; i < factory->count; i++) {
ConcreteCharacter* cc = factory->characters[i];
if (cc->base.symbol == symbol &&
strcmp(cc->font, font) == 0 &&
cc->size == size) {
printf("复用享元对象: '%c'\n", symbol);
return cc; // 返回已存在的对象
}
}
// 不存在,创建新的享元对象
printf("创建新享元对象: '%c'\n", symbol);
ConcreteCharacter* cc = createCharacter(symbol, font, size);
factory->characters[factory->count++] = cc;
return cc;
}
// ========== 外部状态:位置信息 ==========
// 这些是外部状态,不存储在享元对象中
typedef struct {
Character* character; // 享元对象引用
int x; // 外部状态:X坐标
int y; // 外部状态:Y坐标
} CharacterContext;
CharacterContext* createCharacterContext(Character* ch, int x, int y) {
CharacterContext* ctx = (CharacterContext*)malloc(sizeof(CharacterContext));
ctx->character = ch;
ctx->x = x;
ctx->y = y;
return ctx;
}
void displayContext(CharacterContext* ctx) {
ctx->character->display(ctx->character, ctx->x, ctx->y);
}
int main() {
printf("=== 享元模式演示 ===\n\n");
// 创建享元工厂
CharacterFactory* factory = createCharacterFactory();
// 创建字符上下文(包含外部状态)
printf("--- 创建文本 ---\n");
CharacterContext* contexts[10];
int contextCount = 0;
// 创建多个字符,但相同字符会共享享元对象
contexts[contextCount++] = createCharacterContext(
(Character*)getCharacter(factory, 'H', "Arial", 12), 0, 0);
contexts[contextCount++] = createCharacterContext(
(Character*)getCharacter(factory, 'e', "Arial", 12), 10, 0);
contexts[contextCount++] = createCharacterContext(
(Character*)getCharacter(factory, 'l', "Arial", 12), 20, 0);
contexts[contextCount++] = createCharacterContext(
(Character*)getCharacter(factory, 'l', "Arial", 12), 30, 0); // 复用'l'
contexts[contextCount++] = createCharacterContext(
(Character*)getCharacter(factory, 'o', "Arial", 12), 40, 0);
printf("\n--- 显示文本 ---\n");
for (int i = 0; i < contextCount; i++) {
displayContext(contexts[i]);
}
printf("\n--- 统计信息 ---\n");
printf("文本长度: %d 个字符\n", contextCount);
printf("实际创建的享元对象: %d 个\n", factory->count);
printf("节省内存: %d 个对象\n", contextCount - factory->count);
// 释放内存(简化版)
for (int i = 0; i < contextCount; i++) {
free(contexts[i]);
}
for (int i = 0; i < factory->count; i++) {
free(factory->characters[i]);
}
free(factory);
return 0;
}
编译运行:
bash
gcc flyweight.c -o flyweight
./flyweight
7. 代理模式(Proxy Pattern)
通俗解释: 为其他对象提供代理以控制对这个对象的访问。就像代购,你通过代购买东西,代购控制你和商家的交互。
生活例子:
- 代购:代购代理你购买商品
- 门禁卡:门禁卡代理你开门
- 缓存代理:缓存代理数据库,减少数据库访问
适用场景:
- 需要控制对象访问
- 需要延迟加载
- 需要添加额外功能(如缓存、日志)
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> // 用于sleep函数
// ========== 主题接口:图像 ==========
typedef struct {
void (*display)(void* self); // 显示函数
char filename[100];
} Image;
void image_display(void* self) {
Image* img = (Image*)self;
printf("显示图像: %s\n", img->filename);
}
// ========== 真实主题:真实图像 ==========
// 这是实际的对象,可能创建成本很高
typedef struct {
Image base;
} RealImage;
void realImage_display(void* self) {
RealImage* ri = (RealImage*)self;
printf("从磁盘加载图像: %s\n", ri->base.filename);
sleep(1); // 模拟加载时间
printf("显示真实图像: %s\n", ri->base.filename);
}
RealImage* createRealImage(const char* filename) {
RealImage* ri = (RealImage*)malloc(sizeof(RealImage));
strcpy(ri->base.filename, filename);
ri->base.display = realImage_display;
printf("创建真实图像对象: %s\n", filename);
return ri;
}
// ========== 代理:图像代理 ==========
// 代理控制对真实图像的访问
typedef struct {
Image base;
RealImage* realImage; // 真实图像的引用
int loaded; // 是否已加载
} ProxyImage;
void proxyImage_display(void* self) {
ProxyImage* proxy = (ProxyImage*)self;
// 延迟加载:只有在需要时才创建真实对象
if (!proxy->loaded) {
printf("代理:延迟加载图像\n");
proxy->realImage = createRealImage(proxy->base.filename);
proxy->loaded = 1;
}
// 调用真实对象的显示方法
proxy->realImage->base.display(&proxy->realImage->base);
}
ProxyImage* createProxyImage(const char* filename) {
ProxyImage* proxy = (ProxyImage*)malloc(sizeof(ProxyImage));
strcpy(proxy->base.filename, filename);
proxy->base.display = proxyImage_display;
proxy->realImage = NULL;
proxy->loaded = 0;
printf("创建图像代理: %s\n", filename);
return proxy;
}
int main() {
printf("=== 代理模式演示 ===\n\n");
// 创建代理对象(此时真实对象还未创建)
ProxyImage* proxy1 = createProxyImage("photo1.jpg");
ProxyImage* proxy2 = createProxyImage("photo2.jpg");
printf("\n--- 第一次显示图像1 ---\n");
// 第一次调用:代理会创建真实对象
proxy1->base.display(proxy1);
printf("\n--- 第一次显示图像2 ---\n");
proxy2->base.display(proxy2);
printf("\n--- 第二次显示图像1(已缓存) ---\n");
// 第二次调用:直接使用已创建的真实对象
proxy1->base.display(proxy1);
// 释放内存
if (proxy1->realImage) {
free(proxy1->realImage);
}
if (proxy2->realImage) {
free(proxy2->realImage);
}
free(proxy1);
free(proxy2);
return 0;
}
编译运行:
bash
gcc proxy.c -o proxy
./proxy
总结:结构型模式
结构型模式帮助我们组合类和对象,形成更大的结构:
- 适配器模式:让不兼容的接口能够一起工作
- 桥接模式:将抽象和实现分离
- 组合模式:统一处理单个对象和组合对象
- 装饰器模式:动态添加功能
- 外观模式:简化复杂子系统
- 享元模式:共享数据减少内存
- 代理模式:控制对象访问
每种模式都解决了不同的结构问题,让代码更灵活、更易维护。
设计模式详解:行为型模式(11个)
行为型模式关注对象之间的通信和职责分配。
1. 责任链模式(Chain of Responsibility Pattern)
通俗解释: 将请求沿着处理者链传递,直到有处理者处理它。就像请假,先找组长,组长处理不了找经理,经理处理不了找总经理。
生活例子:
- 请假流程:员工 → 组长 → 经理 → 总经理
- 客服系统:一级客服 → 二级客服 → 三级客服
- 异常处理:try-catch链式处理
适用场景:
- 有多个对象可以处理请求
- 不确定哪个对象处理请求
- 需要动态指定处理者
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 请求类型 ==========
typedef struct {
int amount; // 金额
char type[50]; // 类型
} Request;
Request* createRequest(int amount, const char* type) {
Request* req = (Request*)malloc(sizeof(Request));
req->amount = amount;
strcpy(req->type, type);
return req;
}
// ========== 处理者接口 ==========
typedef struct Handler {
struct Handler* next; // 下一个处理者
int limit; // 处理权限上限
char name[50]; // 处理者名称
int (*handle)(struct Handler* self, Request* request); // 处理函数
void (*setNext)(struct Handler* self, struct Handler* next); // 设置下一个处理者
} Handler;
// 设置下一个处理者
void handler_setNext(Handler* self, Handler* next) {
self->next = next;
}
// 处理请求(模板方法)
int handler_handle(Handler* self, Request* request) {
// 如果当前处理者可以处理
if (request->amount <= self->limit) {
printf("%s 处理了请求: %s, 金额: %d\n", self->name, request->type, request->amount);
return 1; // 处理成功
}
// 如果不能处理,传递给下一个处理者
if (self->next != NULL) {
printf("%s 无法处理,传递给下一个处理者\n", self->name);
return self->next->handle(self->next, request);
}
// 没有处理者能处理
printf("没有处理者能处理该请求\n");
return 0;
}
// ========== 具体处理者:组长 ==========
typedef struct {
Handler base;
} GroupLeader;
int groupLeader_handle(Handler* self, Request* request) {
self->limit = 1000; // 组长最多处理1000元
strcpy(self->name, "组长");
return handler_handle(self, request);
}
GroupLeader* createGroupLeader() {
GroupLeader* gl = (GroupLeader*)malloc(sizeof(GroupLeader));
gl->base.handle = groupLeader_handle;
gl->base.setNext = handler_setNext;
gl->base.next = NULL;
return gl;
}
// ========== 具体处理者:经理 ==========
typedef struct {
Handler base;
} Manager;
int manager_handle(Handler* self, Request* request) {
self->limit = 5000; // 经理最多处理5000元
strcpy(self->name, "经理");
return handler_handle(self, request);
}
Manager* createManager() {
Manager* m = (Manager*)malloc(sizeof(Manager));
m->base.handle = manager_handle;
m->base.setNext = handler_setNext;
m->base.next = NULL;
return m;
}
// ========== 具体处理者:总经理 ==========
typedef struct {
Handler base;
} GeneralManager;
int generalManager_handle(Handler* self, Request* request) {
self->limit = 50000; // 总经理最多处理50000元
strcpy(self->name, "总经理");
return handler_handle(self, request);
}
GeneralManager* createGeneralManager() {
GeneralManager* gm = (GeneralManager*)malloc(sizeof(GeneralManager));
gm->base.handle = generalManager_handle;
gm->base.setNext = handler_setNext;
gm->base.next = NULL;
return gm;
}
int main() {
printf("=== 责任链模式演示 ===\n\n");
// 创建处理者链
GroupLeader* leader = createGroupLeader();
Manager* manager = createManager();
GeneralManager* gm = createGeneralManager();
// 设置责任链:组长 -> 经理 -> 总经理
leader->base.setNext(&leader->base, (Handler*)manager);
manager->base.setNext((Handler*)manager, (Handler*)gm);
// 创建不同的请求
printf("--- 请求1: 500元 ---\n");
Request* req1 = createRequest(500, "差旅费");
leader->base.handle((Handler*)leader, req1);
printf("\n--- 请求2: 3000元 ---\n");
Request* req2 = createRequest(3000, "设备采购");
leader->base.handle((Handler*)leader, req2);
printf("\n--- 请求3: 20000元 ---\n");
Request* req3 = createRequest(20000, "项目投资");
leader->base.handle((Handler*)leader, req3);
printf("\n--- 请求4: 100000元(超出所有处理者权限) ---\n");
Request* req4 = createRequest(100000, "大额投资");
leader->base.handle((Handler*)leader, req4);
// 释放内存
free(req1);
free(req2);
free(req3);
free(req4);
free(leader);
free(manager);
free(gm);
return 0;
}
编译运行:
bash
gcc chain_of_responsibility.c -o chain_of_responsibility
./chain_of_responsibility
2. 命令模式(Command Pattern)
通俗解释: 将请求封装成对象,从而可以用不同的请求对客户进行参数化。就像遥控器,每个按钮都是一个命令对象。
生活例子:
- 遥控器:每个按钮是一个命令,可以控制电视
- 菜单:每个菜单项是一个命令
- 撤销/重做:命令可以保存,支持撤销和重做
适用场景:
- 需要将请求参数化
- 需要支持撤销/重做
- 需要记录请求日志
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 接收者:电视 ==========
// 这是实际执行操作的对象
typedef struct {
int volume; // 音量
int channel; // 频道
int isOn; // 是否开机
} TV;
TV* createTV() {
TV* tv = (TV*)malloc(sizeof(TV));
tv->volume = 50;
tv->channel = 1;
tv->isOn = 0;
return tv;
}
void tv_turnOn(TV* tv) {
tv->isOn = 1;
printf("电视已开机\n");
}
void tv_turnOff(TV* tv) {
tv->isOn = 0;
printf("电视已关机\n");
}
void tv_setVolume(TV* tv, int volume) {
tv->volume = volume;
printf("设置音量为: %d\n", volume);
}
void tv_setChannel(TV* tv, int channel) {
tv->channel = channel;
printf("设置频道为: %d\n", channel);
}
void tv_showStatus(TV* tv) {
printf("=== 电视状态 ===\n");
printf("状态: %s\n", tv->isOn ? "开机" : "关机");
printf("音量: %d\n", tv->volume);
printf("频道: %d\n", tv->channel);
printf("==============\n");
}
// ========== 命令接口 ==========
typedef struct {
void (*execute)(void* self); // 执行命令
void (*undo)(void* self); // 撤销命令
char description[100]; // 命令描述
} Command;
// ========== 具体命令:开机命令 ==========
typedef struct {
Command base;
TV* tv;
int previousState; // 保存之前的状态,用于撤销
} TurnOnCommand;
void turnOnCommand_execute(void* self) {
TurnOnCommand* cmd = (TurnOnCommand*)self;
cmd->previousState = cmd->tv->isOn;
tv_turnOn(cmd->tv);
}
void turnOnCommand_undo(void* self) {
TurnOnCommand* cmd = (TurnOnCommand*)self;
if (!cmd->previousState) {
tv_turnOff(cmd->tv);
}
}
TurnOnCommand* createTurnOnCommand(TV* tv) {
TurnOnCommand* cmd = (TurnOnCommand*)malloc(sizeof(TurnOnCommand));
cmd->base.execute = turnOnCommand_execute;
cmd->base.undo = turnOnCommand_undo;
strcpy(cmd->base.description, "开机");
cmd->tv = tv;
return cmd;
}
// ========== 具体命令:关机命令 ==========
typedef struct {
Command base;
TV* tv;
int previousState;
} TurnOffCommand;
void turnOffCommand_execute(void* self) {
TurnOffCommand* cmd = (TurnOffCommand*)self;
cmd->previousState = cmd->tv->isOn;
tv_turnOff(cmd->tv);
}
void turnOffCommand_undo(void* self) {
TurnOffCommand* cmd = (TurnOffCommand*)self;
if (cmd->previousState) {
tv_turnOn(cmd->tv);
}
}
TurnOffCommand* createTurnOffCommand(TV* tv) {
TurnOffCommand* cmd = (TurnOffCommand*)malloc(sizeof(TurnOffCommand));
cmd->base.execute = turnOffCommand_execute;
cmd->base.undo = turnOffCommand_undo;
strcpy(cmd->base.description, "关机");
cmd->tv = tv;
return cmd;
}
// ========== 具体命令:设置音量命令 ==========
typedef struct {
Command base;
TV* tv;
int volume;
int previousVolume;
} SetVolumeCommand;
void setVolumeCommand_execute(void* self) {
SetVolumeCommand* cmd = (SetVolumeCommand*)self;
cmd->previousVolume = cmd->tv->volume;
tv_setVolume(cmd->tv, cmd->volume);
}
void setVolumeCommand_undo(void* self) {
SetVolumeCommand* cmd = (SetVolumeCommand*)self;
tv_setVolume(cmd->tv, cmd->previousVolume);
}
SetVolumeCommand* createSetVolumeCommand(TV* tv, int volume) {
SetVolumeCommand* cmd = (SetVolumeCommand*)malloc(sizeof(SetVolumeCommand));
cmd->base.execute = setVolumeCommand_execute;
cmd->base.undo = setVolumeCommand_undo;
sprintf(cmd->base.description, "设置音量为%d", volume);
cmd->tv = tv;
cmd->volume = volume;
return cmd;
}
// ========== 调用者:遥控器 ==========
// 这是发送命令的对象
typedef struct {
Command* command; // 当前命令
Command* history[100]; // 命令历史(用于撤销)
int historyCount;
} RemoteControl;
RemoteControl* createRemoteControl() {
RemoteControl* rc = (RemoteControl*)malloc(sizeof(RemoteControl));
rc->command = NULL;
rc->historyCount = 0;
return rc;
}
void remoteControl_setCommand(RemoteControl* rc, Command* cmd) {
rc->command = cmd;
}
void remoteControl_pressButton(RemoteControl* rc) {
if (rc->command != NULL) {
printf("执行命令: %s\n", rc->command->description);
rc->command->execute(rc->command);
// 保存到历史
if (rc->historyCount < 100) {
rc->history[rc->historyCount++] = rc->command;
}
}
}
void remoteControl_undo(RemoteControl* rc) {
if (rc->historyCount > 0) {
Command* lastCmd = rc->history[--rc->historyCount];
printf("撤销命令: %s\n", lastCmd->description);
lastCmd->undo(lastCmd);
} else {
printf("没有可撤销的命令\n");
}
}
int main() {
printf("=== 命令模式演示 ===\n\n");
// 创建接收者(电视)
TV* tv = createTV();
tv_showStatus(tv);
// 创建命令
TurnOnCommand* turnOn = createTurnOnCommand(tv);
SetVolumeCommand* setVol = createSetVolumeCommand(tv, 80);
TurnOffCommand* turnOff = createTurnOffCommand(tv);
// 创建调用者(遥控器)
RemoteControl* remote = createRemoteControl();
// 执行命令
printf("\n--- 执行命令 ---\n");
remoteControl_setCommand(remote, (Command*)turnOn);
remoteControl_pressButton(remote);
remoteControl_setCommand(remote, (Command*)setVol);
remoteControl_pressButton(remote);
tv_showStatus(tv);
// 撤销命令
printf("\n--- 撤销命令 ---\n");
remoteControl_undo(remote);
tv_showStatus(tv);
remoteControl_undo(remote);
tv_showStatus(tv);
// 释放内存
free(tv);
free(turnOn);
free(setVol);
free(turnOff);
free(remote);
return 0;
}
编译运行:
bash
gcc command.c -o command
./command
3. 解释器模式(Interpreter Pattern)
通俗解释: 定义语言的文法,并解释该语言中的句子。就像编译器,解释代码的含义。
生活例子:
- 计算器:解释数学表达式
- 正则表达式:解释匹配规则
- SQL解释器:解释SQL语句
适用场景:
- 需要解释特定语言
- 语法简单,性能要求不高
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// ========== 表达式接口 ==========
typedef struct {
int (*interpret)(void* self); // 解释函数
} Expression;
// ========== 终结符表达式:数字 ==========
typedef struct {
Expression base;
int value;
} NumberExpression;
int numberExpression_interpret(void* self) {
NumberExpression* ne = (NumberExpression*)self;
return ne->value;
}
NumberExpression* createNumberExpression(int value) {
NumberExpression* ne = (NumberExpression*)malloc(sizeof(NumberExpression));
ne->base.interpret = numberExpression_interpret;
ne->value = value;
return ne;
}
// ========== 非终结符表达式:加法 ==========
typedef struct {
Expression base;
Expression* left; // 左表达式
Expression* right; // 右表达式
} AddExpression;
int addExpression_interpret(void* self) {
AddExpression* ae = (AddExpression*)self;
int leftValue = ae->left->interpret(ae->left);
int rightValue = ae->right->interpret(ae->right);
return leftValue + rightValue;
}
AddExpression* createAddExpression(Expression* left, Expression* right) {
AddExpression* ae = (AddExpression*)malloc(sizeof(AddExpression));
ae->base.interpret = addExpression_interpret;
ae->left = left;
ae->right = right;
return ae;
}
// ========== 非终结符表达式:减法 ==========
typedef struct {
Expression base;
Expression* left;
Expression* right;
} SubtractExpression;
int subtractExpression_interpret(void* self) {
SubtractExpression* se = (SubtractExpression*)self;
int leftValue = se->left->interpret(se->left);
int rightValue = se->right->interpret(se->right);
return leftValue - rightValue;
}
SubtractExpression* createSubtractExpression(Expression* left, Expression* right) {
SubtractExpression* se = (SubtractExpression*)malloc(sizeof(SubtractExpression));
se->base.interpret = subtractExpression_interpret;
se->left = left;
se->right = right;
return se;
}
// ========== 非终结符表达式:乘法 ==========
typedef struct {
Expression base;
Expression* left;
Expression* right;
} MultiplyExpression;
int multiplyExpression_interpret(void* self) {
MultiplyExpression* me = (MultiplyExpression*)self;
int leftValue = me->left->interpret(me->left);
int rightValue = me->right->interpret(me->right);
return leftValue * rightValue;
}
MultiplyExpression* createMultiplyExpression(Expression* left, Expression* right) {
MultiplyExpression* me = (MultiplyExpression*)malloc(sizeof(MultiplyExpression));
me->base.interpret = multiplyExpression_interpret;
me->left = left;
me->right = right;
return me;
}
// ========== 上下文:解析器 ==========
// 简化版解析器,解析 "数字 运算符 数字" 格式
Expression* parseExpression(const char* expr) {
// 这里简化处理,实际应该用更复杂的解析器
// 示例:解析 "5 + 3" 或 "10 - 2" 或 "4 * 2"
int num1 = 0, num2 = 0;
char op = '+';
// 简单解析(实际应该用词法分析器和语法分析器)
sscanf(expr, "%d %c %d", &num1, &op, &num2);
Expression* left = (Expression*)createNumberExpression(num1);
Expression* right = (Expression*)createNumberExpression(num2);
switch (op) {
case '+':
return (Expression*)createAddExpression(left, right);
case '-':
return (Expression*)createSubtractExpression(left, right);
case '*':
return (Expression*)createMultiplyExpression(left, right);
default:
return left;
}
}
int main() {
printf("=== 解释器模式演示 ===\n\n");
// 创建表达式:5 + 3
Expression* left1 = (Expression*)createNumberExpression(5);
Expression* right1 = (Expression*)createNumberExpression(3);
Expression* expr1 = (Expression*)createAddExpression(left1, right1);
printf("表达式: 5 + 3\n");
printf("结果: %d\n\n", expr1->interpret(expr1));
// 创建表达式:10 - 2
Expression* left2 = (Expression*)createNumberExpression(10);
Expression* right2 = (Expression*)createNumberExpression(2);
Expression* expr2 = (Expression*)createSubtractExpression(left2, right2);
printf("表达式: 10 - 2\n");
printf("结果: %d\n\n", expr2->interpret(expr2));
// 创建表达式:4 * 2
Expression* left3 = (Expression*)createNumberExpression(4);
Expression* right3 = (Expression*)createNumberExpression(2);
Expression* expr3 = (Expression*)createMultiplyExpression(left3, right3);
printf("表达式: 4 * 2\n");
printf("结果: %d\n\n", expr3->interpret(expr3));
// 复杂表达式:(5 + 3) * 2
Expression* complexLeft = (Expression*)createAddExpression(
(Expression*)createNumberExpression(5),
(Expression*)createNumberExpression(3)
);
Expression* complexRight = (Expression*)createNumberExpression(2);
Expression* complexExpr = (Expression*)createMultiplyExpression(complexLeft, complexRight);
printf("表达式: (5 + 3) * 2\n");
printf("结果: %d\n\n", complexExpr->interpret(complexExpr));
// 释放内存(简化版)
free(left1);
free(right1);
free(expr1);
free(left2);
free(right2);
free(expr2);
free(left3);
free(right3);
free(expr3);
free(complexLeft);
free(complexRight);
free(complexExpr);
return 0;
}
编译运行:
bash
gcc interpreter.c -o interpreter
./interpreter
4. 迭代器模式(Iterator Pattern)
通俗解释: 提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。就像遥控器,可以顺序切换电视频道。
生活例子:
- 遥控器:顺序切换频道
- 书签:顺序浏览网页
- 播放列表:顺序播放歌曲
适用场景:
- 需要遍历集合
- 需要统一遍历接口
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 迭代器接口 ==========
typedef struct {
int (*hasNext)(void* self); // 是否有下一个元素
void* (*next)(void* self); // 获取下一个元素
void (*reset)(void* self); // 重置迭代器
} Iterator;
// ========== 聚合接口 ==========
typedef struct {
Iterator* (*createIterator)(void* self); // 创建迭代器
int size; // 集合大小
} Aggregate;
// ========== 具体聚合:数组集合 ==========
typedef struct {
Aggregate base;
int* data; // 数据数组
int capacity; // 容量
} ArrayCollection;
// ========== 具体迭代器:数组迭代器 ==========
typedef struct {
Iterator base;
ArrayCollection* collection; // 关联的集合
int currentIndex; // 当前索引
} ArrayIterator;
int arrayIterator_hasNext(void* self) {
ArrayIterator* it = (ArrayIterator*)self;
return it->currentIndex < it->collection->base.size;
}
void* arrayIterator_next(void* self) {
ArrayIterator* it = (ArrayIterator*)self;
if (it->hasNext(it)) {
void* item = &it->collection->data[it->currentIndex++];
return item;
}
return NULL;
}
void arrayIterator_reset(void* self) {
ArrayIterator* it = (ArrayIterator*)self;
it->currentIndex = 0;
}
Iterator* arrayIterator_create(ArrayCollection* collection) {
ArrayIterator* it = (ArrayIterator*)malloc(sizeof(ArrayIterator));
it->base.hasNext = arrayIterator_hasNext;
it->base.next = arrayIterator_next;
it->base.reset = arrayIterator_reset;
it->collection = collection;
it->currentIndex = 0;
return (Iterator*)it;
}
Iterator* arrayCollection_createIterator(void* self) {
ArrayCollection* ac = (ArrayCollection*)self;
return arrayIterator_create(ac);
}
ArrayCollection* createArrayCollection(int capacity) {
ArrayCollection* ac = (ArrayCollection*)malloc(sizeof(ArrayCollection));
ac->data = (int*)malloc(sizeof(int) * capacity);
ac->capacity = capacity;
ac->base.size = 0;
ac->base.createIterator = arrayCollection_createIterator;
return ac;
}
void arrayCollection_add(ArrayCollection* ac, int value) {
if (ac->base.size < ac->capacity) {
ac->data[ac->base.size++] = value;
}
}
// ========== 客户端代码 ==========
void traverseCollection(Aggregate* aggregate) {
printf("遍历集合:\n");
Iterator* it = aggregate->createIterator(aggregate);
int index = 0;
while (it->hasNext(it)) {
int* value = (int*)it->next(it);
printf(" 元素[%d]: %d\n", index++, *value);
}
free(it);
}
int main() {
printf("=== 迭代器模式演示 ===\n\n");
// 创建集合
ArrayCollection* collection = createArrayCollection(10);
// 添加元素
arrayCollection_add(collection, 10);
arrayCollection_add(collection, 20);
arrayCollection_add(collection, 30);
arrayCollection_add(collection, 40);
arrayCollection_add(collection, 50);
printf("集合大小: %d\n\n", collection->base.size);
// 使用迭代器遍历
traverseCollection((Aggregate*)collection);
// 手动使用迭代器
printf("\n手动遍历:\n");
Iterator* it = collection->base.createIterator(collection);
while (it->hasNext(it)) {
int* value = (int*)it->next(it);
printf("值: %d\n", *value);
}
// 重置迭代器
printf("\n重置后再次遍历:\n");
it->reset(it);
while (it->hasNext(it)) {
int* value = (int*)it->next(it);
printf("值: %d\n", *value);
}
// 释放内存
free(it);
free(collection->data);
free(collection);
return 0;
}
编译运行:
bash
gcc iterator.c -o iterator
./iterator
5. 中介者模式(Mediator Pattern)
通俗解释: 用一个中介对象来封装一系列对象的交互。就像聊天室,所有人通过聊天室交流,而不是直接互相联系。
生活例子:
- 聊天室:所有人通过聊天室交流
- 机场塔台:所有飞机通过塔台协调
- 股票交易所:所有交易通过交易所进行
适用场景:
- 对象之间有很多交互
- 需要解耦对象之间的直接依赖
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 中介者接口 ==========
typedef struct Mediator {
void (*sendMessage)(struct Mediator* self, const char* from, const char* to, const char* message);
} Mediator;
// ========== 同事接口 ==========
typedef struct Colleague {
char name[50];
Mediator* mediator; // 中介者引用
void (*send)(struct Colleague* self, const char* to, const char* message);
void (*receive)(struct Colleague* self, const char* from, const char* message);
} Colleague;
void colleague_send(Colleague* self, const char* to, const char* message) {
printf("%s 发送消息给 %s: %s\n", self->name, to, message);
self->mediator->sendMessage(self->mediator, self->name, to, message);
}
void colleague_receive(Colleague* self, const char* from, const char* message) {
printf("%s 收到来自 %s 的消息: %s\n", self->name, from, message);
}
// ========== 具体中介者:聊天室 ==========
typedef struct {
Mediator base;
Colleague* colleagues[10]; // 注册的同事
int count;
} ChatRoom;
void chatRoom_sendMessage(Mediator* self, const char* from, const char* to, const char* message) {
ChatRoom* cr = (ChatRoom*)self;
// 查找接收者
for (int i = 0; i < cr->count; i++) {
if (strcmp(cr->colleagues[i]->name, to) == 0) {
cr->colleagues[i]->receive(cr->colleagues[i], from, message);
return;
}
}
// 如果没找到接收者,可能是群发消息
if (strcmp(to, "所有人") == 0) {
printf("--- 群发消息 ---\n");
for (int i = 0; i < cr->count; i++) {
if (strcmp(cr->colleagues[i]->name, from) != 0) {
cr->colleagues[i]->receive(cr->colleagues[i], from, message);
}
}
} else {
printf("错误:找不到用户 %s\n", to);
}
}
ChatRoom* createChatRoom() {
ChatRoom* cr = (ChatRoom*)malloc(sizeof(ChatRoom));
cr->base.sendMessage = chatRoom_sendMessage;
cr->count = 0;
return cr;
}
void chatRoom_register(ChatRoom* cr, Colleague* colleague) {
if (cr->count < 10) {
cr->colleagues[cr->count++] = colleague;
colleague->mediator = (Mediator*)cr;
printf("%s 加入聊天室\n", colleague->name);
}
}
// ========== 具体同事:用户 ==========
typedef struct {
Colleague base;
} User;
User* createUser(const char* name) {
User* user = (User*)malloc(sizeof(User));
strcpy(user->base.name, name);
user->base.send = colleague_send;
user->base.receive = colleague_receive;
user->base.mediator = NULL;
return user;
}
int main() {
printf("=== 中介者模式演示 ===\n\n");
// 创建中介者(聊天室)
ChatRoom* chatRoom = createChatRoom();
// 创建用户
User* alice = createUser("Alice");
User* bob = createUser("Bob");
User* charlie = createUser("Charlie");
// 注册到聊天室
chatRoom_register(chatRoom, (Colleague*)alice);
chatRoom_register(chatRoom, (Colleague*)bob);
chatRoom_register(chatRoom, (Colleague*)charlie);
printf("\n--- 开始聊天 ---\n");
// 用户通过中介者(聊天室)发送消息
alice->base.send((Colleague*)alice, "Bob", "你好,Bob!");
printf("\n");
bob->base.send((Colleague*)bob, "Alice", "你好,Alice!");
printf("\n");
charlie->base.send((Colleague*)charlie, "所有人", "大家好!");
// 释放内存
free(alice);
free(bob);
free(charlie);
free(chatRoom);
return 0;
}
编译运行:
bash
gcc mediator.c -o mediator
./mediator
6. 备忘录模式(Memento Pattern)
通俗解释: 在不破坏封装性的前提下,捕获对象的内部状态,并在对象之外保存这个状态。就像游戏存档,可以保存和恢复游戏状态。
生活例子:
- 游戏存档:保存游戏状态,可以恢复
- 撤销功能:保存操作历史,可以撤销
- 数据库事务:保存事务状态,可以回滚
适用场景:
- 需要保存对象状态
- 需要支持撤销功能
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 备忘录:保存状态 ==========
typedef struct {
int level; // 关卡
int score; // 分数
int health; // 生命值
char state[100]; // 状态描述
} Memento;
Memento* createMemento(int level, int score, int health, const char* state) {
Memento* m = (Memento*)malloc(sizeof(Memento));
m->level = level;
m->score = score;
m->health = health;
strcpy(m->state, state);
return m;
}
void memento_display(Memento* m) {
printf("=== 存档信息 ===\n");
printf("关卡: %d\n", m->level);
printf("分数: %d\n", m->score);
printf("生命值: %d\n", m->health);
printf("状态: %s\n", m->state);
printf("==============\n");
}
// ========== 原发器:游戏角色 ==========
// 需要保存状态的对象
typedef struct {
int level;
int score;
int health;
char state[100];
Memento* (*save)(void* self); // 保存状态
void (*restore)(void* self, Memento* m); // 恢复状态
void (*play)(void* self); // 游戏操作
void (*display)(void* self); // 显示状态
} GameCharacter;
Memento* gameCharacter_save(void* self) {
GameCharacter* gc = (GameCharacter*)self;
sprintf(gc->state, "关卡%d-分数%d-生命%d", gc->level, gc->score, gc->health);
return createMemento(gc->level, gc->score, gc->health, gc->state);
}
void gameCharacter_restore(void* self, Memento* m) {
GameCharacter* gc = (GameCharacter*)self;
gc->level = m->level;
gc->score = m->score;
gc->health = m->health;
strcpy(gc->state, m->state);
printf("恢复游戏状态\n");
}
void gameCharacter_play(void* self) {
GameCharacter* gc = (GameCharacter*)self;
gc->level++;
gc->score += 100;
gc->health -= 10;
sprintf(gc->state, "关卡%d-分数%d-生命%d", gc->level, gc->score, gc->health);
printf("游戏进行中...\n");
}
void gameCharacter_display(void* self) {
GameCharacter* gc = (GameCharacter*)self;
printf("=== 当前游戏状态 ===\n");
printf("关卡: %d\n", gc->level);
printf("分数: %d\n", gc->score);
printf("生命值: %d\n", gc->health);
printf("状态: %s\n", gc->state);
printf("==================\n");
}
GameCharacter* createGameCharacter() {
GameCharacter* gc = (GameCharacter*)malloc(sizeof(GameCharacter));
gc->level = 1;
gc->score = 0;
gc->health = 100;
strcpy(gc->state, "初始状态");
gc->save = gameCharacter_save;
gc->restore = gameCharacter_restore;
gc->play = gameCharacter_play;
gc->display = gameCharacter_display;
return gc;
}
// ========== 管理者:存档管理器 ==========
// 负责保存和管理备忘录
typedef struct {
Memento* mementos[10]; // 存档列表
int count;
} Caretaker;
Caretaker* createCaretaker() {
Caretaker* ct = (Caretaker*)malloc(sizeof(Caretaker));
ct->count = 0;
return ct;
}
void caretaker_save(Caretaker* ct, Memento* m) {
if (ct->count < 10) {
ct->mementos[ct->count++] = m;
printf("存档成功(存档%d)\n", ct->count);
} else {
printf("存档已满\n");
}
}
Memento* caretaker_load(Caretaker* ct, int index) {
if (index >= 1 && index <= ct->count) {
printf("加载存档%d\n", index);
return ct->mementos[index - 1];
}
printf("存档不存在\n");
return NULL;
}
int main() {
printf("=== 备忘录模式演示 ===\n\n");
// 创建游戏角色
GameCharacter* character = createGameCharacter();
character->display(character);
// 创建存档管理器
Caretaker* caretaker = createCaretaker();
// 保存初始状态
printf("\n--- 保存初始状态 ---\n");
Memento* save1 = character->save(character);
caretaker_save(caretaker, save1);
// 游戏进行
printf("\n--- 游戏进行 ---\n");
character->play(character);
character->display(character);
// 保存进度
printf("\n--- 保存进度1 ---\n");
Memento* save2 = character->save(character);
caretaker_save(caretaker, save2);
// 继续游戏
printf("\n--- 继续游戏 ---\n");
character->play(character);
character->display(character);
// 恢复存档1
printf("\n--- 恢复到存档1 ---\n");
Memento* loaded = caretaker_load(caretaker, 1);
if (loaded) {
memento_display(loaded);
character->restore(character, loaded);
character->display(character);
}
// 释放内存(简化版)
free(character);
for (int i = 0; i < caretaker->count; i++) {
free(caretaker->mementos[i]);
}
free(caretaker);
return 0;
}
编译运行:
bash
gcc memento.c -o memento
./memento
7. 观察者模式(Observer Pattern)
通俗解释: 定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知。就像订阅报纸,报纸更新时,所有订阅者都会收到。
生活例子:
- 订阅报纸:报纸更新,订阅者收到
- 微信朋友圈:发朋友圈,好友收到通知
- 股票价格:价格变化,所有关注者收到通知
适用场景:
- 一个对象状态改变需要通知多个对象
- 需要解耦观察者和被观察者
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 观察者接口 ==========
typedef struct Observer {
char name[50];
void (*update)(struct Observer* self, const char* message); // 更新函数
} Observer;
// ========== 主题接口 ==========
typedef struct Subject {
Observer* observers[10]; // 观察者列表
int observerCount; // 观察者数量
void (*attach)(struct Subject* self, Observer* observer); // 添加观察者
void (*detach)(struct Subject* self, Observer* observer); // 移除观察者
void (*notify)(struct Subject* self, const char* message); // 通知观察者
} Subject;
void subject_attach(Subject* self, Observer* observer) {
if (self->observerCount < 10) {
self->observers[self->observerCount++] = observer;
printf("%s 订阅了主题\n", observer->name);
}
}
void subject_detach(Subject* self, Observer* observer) {
for (int i = 0; i < self->observerCount; i++) {
if (self->observers[i] == observer) {
// 移除观察者
for (int j = i; j < self->observerCount - 1; j++) {
self->observers[j] = self->observers[j + 1];
}
self->observerCount--;
printf("%s 取消订阅\n", observer->name);
return;
}
}
}
void subject_notify(Subject* self, const char* message) {
printf("\n--- 通知所有观察者 ---\n");
for (int i = 0; i < self->observerCount; i++) {
self->observers[i]->update(self->observers[i], message);
}
}
// ========== 具体主题:新闻发布者 ==========
typedef struct {
Subject base;
char news[200]; // 新闻内容
} NewsPublisher;
NewsPublisher* createNewsPublisher() {
NewsPublisher* np = (NewsPublisher*)malloc(sizeof(NewsPublisher));
np->base.attach = subject_attach;
np->base.detach = subject_detach;
np->base.notify = subject_notify;
np->base.observerCount = 0;
strcpy(np->news, "");
return np;
}
void newsPublisher_publish(NewsPublisher* np, const char* news) {
strcpy(np->news, news);
printf("发布新闻: %s\n", news);
np->base.notify(&np->base, news);
}
// ========== 具体观察者:订阅者 ==========
typedef struct {
Observer base;
} NewsSubscriber;
void newsSubscriber_update(Observer* self, const char* message) {
printf("%s 收到新闻: %s\n", self->name, message);
}
NewsSubscriber* createNewsSubscriber(const char* name) {
NewsSubscriber* ns = (NewsSubscriber*)malloc(sizeof(NewsSubscriber));
strcpy(ns->base.name, name);
ns->base.update = newsSubscriber_update;
return ns;
}
int main() {
printf("=== 观察者模式演示 ===\n\n");
// 创建主题(新闻发布者)
NewsPublisher* publisher = createNewsPublisher();
// 创建观察者(订阅者)
NewsSubscriber* subscriber1 = createNewsSubscriber("张三");
NewsSubscriber* subscriber2 = createNewsSubscriber("李四");
NewsSubscriber* subscriber3 = createNewsSubscriber("王五");
// 订阅
publisher->base.attach(&publisher->base, (Observer*)subscriber1);
publisher->base.attach(&publisher->base, (Observer*)subscriber2);
publisher->base.attach(&publisher->base, (Observer*)subscriber3);
// 发布新闻
printf("\n");
newsPublisher_publish(publisher, "今天天气很好!");
// 取消订阅
printf("\n");
publisher->base.detach(&publisher->base, (Observer*)subscriber2);
// 再次发布新闻
printf("\n");
newsPublisher_publish(publisher, "明天要下雨了!");
// 释放内存
free(publisher);
free(subscriber1);
free(subscriber2);
free(subscriber3);
return 0;
}
编译运行:
bash
gcc observer.c -o observer
./observer
8. 状态模式(State Pattern)
通俗解释: 允许对象在内部状态改变时改变它的行为。就像自动售货机,不同状态(有货/无货)有不同的行为。
生活例子:
- 自动售货机:有货/无货状态,行为不同
- 交通灯:红灯/绿灯/黄灯状态
- 游戏角色:正常/受伤/死亡状态
适用场景:
- 对象行为依赖于状态
- 需要根据状态改变行为
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 状态接口 ==========
typedef struct State {
void (*handle)(void* self); // 处理函数
char name[50];
} State;
// ========== 上下文:自动售货机 ==========
typedef struct {
State* currentState; // 当前状态
int itemCount; // 商品数量
void (*request)(void* self); // 请求操作
void (*setState)(void* self, State* state); // 设置状态
} VendingMachine;
void vendingMachine_request(void* self) {
VendingMachine* vm = (VendingMachine*)self;
printf("当前状态: %s\n", vm->currentState->name);
vm->currentState->handle(vm->currentState);
}
void vendingMachine_setState(void* self, State* state) {
VendingMachine* vm = (VendingMachine*)self;
vm->currentState = state;
printf("状态切换为: %s\n", state->name);
}
VendingMachine* createVendingMachine() {
VendingMachine* vm = (VendingMachine*)malloc(sizeof(VendingMachine));
vm->itemCount = 0;
vm->request = vendingMachine_request;
vm->setState = vendingMachine_setState;
return vm;
}
// ========== 具体状态:有货状态 ==========
typedef struct {
State base;
VendingMachine* machine;
} HasItemState;
void hasItemState_handle(void* self) {
HasItemState* state = (HasItemState*)self;
printf("有货状态:可以购买\n");
state->machine->itemCount--;
printf("售出一件商品,剩余: %d\n", state->machine->itemCount);
// 如果商品售完,切换到无货状态
if (state->machine->itemCount == 0) {
// 这里简化处理,实际应该通过状态管理器切换
printf("商品售完,切换到无货状态\n");
}
}
HasItemState* createHasItemState(VendingMachine* machine) {
HasItemState* state = (HasItemState*)malloc(sizeof(HasItemState));
strcpy(state->base.name, "有货");
state->base.handle = hasItemState_handle;
state->machine = machine;
return state;
}
// ========== 具体状态:无货状态 ==========
typedef struct {
State base;
VendingMachine* machine;
} NoItemState;
void noItemState_handle(void* self) {
NoItemState* state = (NoItemState*)self;
printf("无货状态:无法购买,请补货\n");
}
NoItemState* createNoItemState(VendingMachine* machine) {
NoItemState* state = (NoItemState*)malloc(sizeof(NoItemState));
strcpy(state->base.name, "无货");
state->base.handle = noItemState_handle;
state->machine = machine;
return state;
}
int main() {
printf("=== 状态模式演示 ===\n\n");
// 创建自动售货机
VendingMachine* machine = createVendingMachine();
machine->itemCount = 3; // 初始有3件商品
// 创建状态
HasItemState* hasItem = createHasItemState(machine);
NoItemState* noItem = createNoItemState(machine);
// 设置初始状态
machine->setState(machine, (State*)hasItem);
// 购买商品
printf("\n--- 购买商品1 ---\n");
machine->request(machine);
printf("\n--- 购买商品2 ---\n");
machine->request(machine);
printf("\n--- 购买商品3 ---\n");
machine->request(machine);
// 切换到无货状态
printf("\n--- 商品售完 ---\n");
machine->setState(machine, (State*)noItem);
// 尝试购买(无货)
printf("\n--- 尝试购买(无货) ---\n");
machine->request(machine);
// 释放内存
free(machine);
free(hasItem);
free(noItem);
return 0;
}
编译运行:
bash
gcc state.c -o state
./state
9. 策略模式(Strategy Pattern)
通俗解释: 定义一系列算法,把它们封装起来,并且使它们可以互换。就像支付方式,可以用支付宝、微信、信用卡等不同策略。
生活例子:
- 支付方式:支付宝、微信、信用卡等不同策略
- 排序算法:快速排序、冒泡排序、归并排序等
- 导航方式:步行、开车、公交等不同路线策略
适用场景:
- 需要在运行时选择算法
- 有多个相似的类,只是行为不同
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 策略接口:支付策略 ==========
typedef struct {
void (*pay)(void* self, double amount); // 支付函数
char name[50];
} PaymentStrategy;
// ========== 具体策略:支付宝支付 ==========
typedef struct {
PaymentStrategy base;
} AlipayStrategy;
void alipayStrategy_pay(void* self, double amount) {
printf("使用支付宝支付: %.2f 元\n", amount);
printf("跳转到支付宝支付页面...\n");
printf("支付成功!\n");
}
AlipayStrategy* createAlipayStrategy() {
AlipayStrategy* strategy = (AlipayStrategy*)malloc(sizeof(AlipayStrategy));
strcpy(strategy->base.name, "支付宝");
strategy->base.pay = alipayStrategy_pay;
return strategy;
}
// ========== 具体策略:微信支付 ==========
typedef struct {
PaymentStrategy base;
} WeChatStrategy;
void weChatStrategy_pay(void* self, double amount) {
printf("使用微信支付: %.2f 元\n", amount);
printf("打开微信支付...\n");
printf("支付成功!\n");
}
WeChatStrategy* createWeChatStrategy() {
WeChatStrategy* strategy = (WeChatStrategy*)malloc(sizeof(WeChatStrategy));
strcpy(strategy->base.name, "微信");
strategy->base.pay = weChatStrategy_pay;
return strategy;
}
// ========== 具体策略:信用卡支付 ==========
typedef struct {
PaymentStrategy base;
} CreditCardStrategy;
void creditCardStrategy_pay(void* self, double amount) {
printf("使用信用卡支付: %.2f 元\n", amount);
printf("输入信用卡信息...\n");
printf("支付成功!\n");
}
CreditCardStrategy* createCreditCardStrategy() {
CreditCardStrategy* strategy = (CreditCardStrategy*)malloc(sizeof(CreditCardStrategy));
strcpy(strategy->base.name, "信用卡");
strategy->base.pay = creditCardStrategy_pay;
return strategy;
}
// ========== 上下文:购物车 ==========
typedef struct {
PaymentStrategy* strategy; // 当前支付策略
double total; // 总金额
void (*setPaymentStrategy)(void* self, PaymentStrategy* strategy); // 设置支付策略
void (*checkout)(void* self); // 结账
void (*addItem)(void* self, double price); // 添加商品
} ShoppingCart;
void shoppingCart_setPaymentStrategy(void* self, PaymentStrategy* strategy) {
ShoppingCart* cart = (ShoppingCart*)self;
cart->strategy = strategy;
printf("设置支付方式为: %s\n", strategy->name);
}
void shoppingCart_checkout(void* self) {
ShoppingCart* cart = (ShoppingCart*)self;
if (cart->strategy == NULL) {
printf("错误:未设置支付方式\n");
return;
}
printf("\n=== 结账 ===\n");
printf("总金额: %.2f 元\n", cart->total);
cart->strategy->pay(cart->strategy, cart->total);
printf("===========\n\n");
}
void shoppingCart_addItem(void* self, double price) {
ShoppingCart* cart = (ShoppingCart*)self;
cart->total += price;
printf("添加商品,价格: %.2f 元,总计: %.2f 元\n", price, cart->total);
}
ShoppingCart* createShoppingCart() {
ShoppingCart* cart = (ShoppingCart*)malloc(sizeof(ShoppingCart));
cart->strategy = NULL;
cart->total = 0.0;
cart->setPaymentStrategy = shoppingCart_setPaymentStrategy;
cart->checkout = shoppingCart_checkout;
cart->addItem = shoppingCart_addItem;
return cart;
}
int main() {
printf("=== 策略模式演示 ===\n\n");
// 创建购物车
ShoppingCart* cart = createShoppingCart();
// 添加商品
cart->addItem(cart, 100.0);
cart->addItem(cart, 50.0);
cart->addItem(cart, 30.0);
// 使用不同的支付策略
printf("\n--- 使用支付宝支付 ---\n");
AlipayStrategy* alipay = createAlipayStrategy();
cart->setPaymentStrategy(cart, (PaymentStrategy*)alipay);
cart->checkout(cart);
// 重置购物车
cart->total = 180.0;
printf("--- 使用微信支付 ---\n");
WeChatStrategy* wechat = createWeChatStrategy();
cart->setPaymentStrategy(cart, (PaymentStrategy*)wechat);
cart->checkout(cart);
// 重置购物车
cart->total = 180.0;
printf("--- 使用信用卡支付 ---\n");
CreditCardStrategy* credit = createCreditCardStrategy();
cart->setPaymentStrategy(cart, (PaymentStrategy*)credit);
cart->checkout(cart);
// 释放内存
free(cart);
free(alipay);
free(wechat);
free(credit);
return 0;
}
编译运行:
bash
gcc strategy.c -o strategy
./strategy
10. 模板方法模式(Template Method Pattern)
通俗解释: 定义一个操作中算法的骨架,而将一些步骤延迟到子类中。就像做菜,步骤固定(洗菜、切菜、炒菜),但具体做法可以不同。
生活例子:
- 做菜:步骤固定,但具体做法不同
- 考试:流程固定(发卷、答题、收卷),但题目不同
- 银行开户:流程固定,但不同银行细节不同
适用场景:
- 有多个类有相似的算法结构
- 需要控制算法的流程
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 抽象类:饮料制作模板 ==========
typedef struct {
void (*brew)(void* self); // 冲泡(抽象方法)
void (*addCondiments)(void* self); // 添加调料(抽象方法)
void (*makeBeverage)(void* self); // 制作饮料(模板方法)
} BeverageTemplate;
// 模板方法:定义算法骨架
void beverageTemplate_makeBeverage(void* self) {
BeverageTemplate* bt = (BeverageTemplate*)self;
printf("=== 开始制作饮料 ===\n");
printf("步骤1: 烧水\n");
printf("步骤2: ");
bt->brew(bt); // 调用具体实现
printf("步骤3: 倒入杯子\n");
printf("步骤4: ");
bt->addCondiments(bt); // 调用具体实现
printf("步骤5: 完成\n");
printf("==================\n\n");
}
// ========== 具体类:咖啡 ==========
typedef struct {
BeverageTemplate base;
} Coffee;
void coffee_brew(void* self) {
printf("冲泡咖啡\n");
}
void coffee_addCondiments(void* self) {
printf("添加糖和牛奶\n");
}
Coffee* createCoffee() {
Coffee* coffee = (Coffee*)malloc(sizeof(Coffee));
coffee->base.brew = coffee_brew;
coffee->base.addCondiments = coffee_addCondiments;
coffee->base.makeBeverage = beverageTemplate_makeBeverage;
return coffee;
}
// ========== 具体类:茶 ==========
typedef struct {
BeverageTemplate base;
} Tea;
void tea_brew(void* self) {
printf("冲泡茶叶\n");
}
void tea_addCondiments(void* self) {
printf("添加柠檬\n");
}
Tea* createTea() {
Tea* tea = (Tea*)malloc(sizeof(Tea));
tea->base.brew = tea_brew;
tea->base.addCondiments = tea_addCondiments;
tea->base.makeBeverage = beverageTemplate_makeBeverage;
return tea;
}
// ========== 具体类:纯咖啡(不添加调料) ==========
typedef struct {
BeverageTemplate base;
} BlackCoffee;
void blackCoffee_brew(void* self) {
printf("冲泡咖啡\n");
}
void blackCoffee_addCondiments(void* self) {
printf("不添加任何调料(纯咖啡)\n");
}
BlackCoffee* createBlackCoffee() {
BlackCoffee* bc = (BlackCoffee*)malloc(sizeof(BlackCoffee));
bc->base.brew = blackCoffee_brew;
bc->base.addCondiments = blackCoffee_addCondiments;
bc->base.makeBeverage = beverageTemplate_makeBeverage;
return bc;
}
int main() {
printf("=== 模板方法模式演示 ===\n\n");
// 制作咖啡
Coffee* coffee = createCoffee();
coffee->base.makeBeverage(&coffee->base);
// 制作茶
Tea* tea = createTea();
tea->base.makeBeverage(&tea->base);
// 制作纯咖啡
BlackCoffee* blackCoffee = createBlackCoffee();
blackCoffee->base.makeBeverage(&blackCoffee->base);
// 释放内存
free(coffee);
free(tea);
free(blackCoffee);
return 0;
}
编译运行:
bash
gcc template_method.c -o template_method
./template_method
11. 访问者模式(Visitor Pattern)
通俗解释: 表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素类的前提下定义作用于这些元素的新操作。就像医生访问病人,对不同病人做不同检查。
生活例子:
- 医生访问病人:对不同病人做不同检查
- 税务审计:对不同公司做不同审计
- 编译器:对不同语法节点做不同处理
适用场景:
- 需要对对象结构中的元素执行不同操作
- 需要在不改变元素类的情况下添加新操作
C语言实现:
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ========== 访问者接口 ==========
typedef struct Visitor {
void (*visitElementA)(struct Visitor* self, void* element); // 访问元素A
void (*visitElementB)(struct Visitor* self, void* element); // 访问元素B
} Visitor;
// ========== 元素接口 ==========
typedef struct Element {
void (*accept)(void* self, Visitor* visitor); // 接受访问者
char name[50];
} Element;
// ========== 具体元素A ==========
typedef struct {
Element base;
int valueA;
} ConcreteElementA;
void elementA_accept(void* self, Visitor* visitor) {
ConcreteElementA* elem = (ConcreteElementA*)self;
printf("%s 接受访问\n", elem->base.name);
visitor->visitElementA(visitor, elem);
}
ConcreteElementA* createElementA(const char* name, int value) {
ConcreteElementA* elem = (ConcreteElementA*)malloc(sizeof(ConcreteElementA));
strcpy(elem->base.name, name);
elem->base.accept = elementA_accept;
elem->valueA = value;
return elem;
}
// ========== 具体元素B ==========
typedef struct {
Element base;
char valueB[50];
} ConcreteElementB;
void elementB_accept(void* self, Visitor* visitor) {
ConcreteElementB* elem = (ConcreteElementB*)self;
printf("%s 接受访问\n", elem->base.name);
visitor->visitElementB(visitor, elem);
}
ConcreteElementB* createElementB(const char* name, const char* value) {
ConcreteElementB* elem = (ConcreteElementB*)malloc(sizeof(ConcreteElementB));
strcpy(elem->base.name, name);
elem->base.accept = elementB_accept;
strcpy(elem->valueB, value);
return elem;
}
// ========== 具体访问者:操作1 ==========
typedef struct {
Visitor base;
} ConcreteVisitor1;
void visitor1_visitElementA(Visitor* self, void* element) {
ConcreteElementA* elem = (ConcreteElementA*)element;
printf("访问者1 访问元素A: %s,执行操作1,值: %d\n", elem->base.name, elem->valueA);
}
void visitor1_visitElementB(Visitor* self, void* element) {
ConcreteElementB* elem = (ConcreteElementB*)element;
printf("访问者1 访问元素B: %s,执行操作1,值: %s\n", elem->base.name, elem->valueB);
}
ConcreteVisitor1* createVisitor1() {
ConcreteVisitor1* v = (ConcreteVisitor1*)malloc(sizeof(ConcreteVisitor1));
v->base.visitElementA = visitor1_visitElementA;
v->base.visitElementB = visitor1_visitElementB;
return v;
}
// ========== 具体访问者:操作2 ==========
typedef struct {
Visitor base;
} ConcreteVisitor2;
void visitor2_visitElementA(Visitor* self, void* element) {
ConcreteElementA* elem = (ConcreteElementA*)element;
printf("访问者2 访问元素A: %s,执行操作2,值: %d\n", elem->base.name, elem->valueA);
}
void visitor2_visitElementB(Visitor* self, void* element) {
ConcreteElementB* elem = (ConcreteElementB*)element;
printf("访问者2 访问元素B: %s,执行操作2,值: %s\n", elem->base.name, elem->valueB);
}
ConcreteVisitor2* createVisitor2() {
ConcreteVisitor2* v = (ConcreteVisitor2*)malloc(sizeof(ConcreteVisitor2));
v->base.visitElementA = visitor2_visitElementA;
v->base.visitElementB = visitor2_visitElementB;
return v;
}
// ========== 对象结构 ==========
typedef struct {
Element* elements[10];
int count;
void (*add)(void* self, Element* element);
void (*accept)(void* self, Visitor* visitor);
} ObjectStructure;
void objectStructure_add(void* self, Element* element) {
ObjectStructure* os = (ObjectStructure*)self;
if (os->count < 10) {
os->elements[os->count++] = element;
}
}
void objectStructure_accept(void* self, Visitor* visitor) {
ObjectStructure* os = (ObjectStructure*)self;
printf("\n=== 访问对象结构 ===\n");
for (int i = 0; i < os->count; i++) {
os->elements[i]->accept(os->elements[i], visitor);
}
printf("==================\n\n");
}
ObjectStructure* createObjectStructure() {
ObjectStructure* os = (ObjectStructure*)malloc(sizeof(ObjectStructure));
os->count = 0;
os->add = objectStructure_add;
os->accept = objectStructure_accept;
return os;
}
int main() {
printf("=== 访问者模式演示 ===\n\n");
// 创建元素
ConcreteElementA* elemA = createElementA("元素A", 100);
ConcreteElementB* elemB = createElementB("元素B", "Hello");
// 创建对象结构
ObjectStructure* structure = createObjectStructure();
structure->add(structure, (Element*)elemA);
structure->add(structure, (Element*)elemB);
// 使用访问者1访问
ConcreteVisitor1* visitor1 = createVisitor1();
structure->accept(structure, (Visitor*)visitor1);
// 使用访问者2访问
ConcreteVisitor2* visitor2 = createVisitor2();
structure->accept(structure, (Visitor*)visitor2);
// 释放内存
free(elemA);
free(elemB);
free(structure);
free(visitor1);
free(visitor2);
return 0;
}
编译运行:
bash
gcc visitor.c -o visitor
./visitor
总结:行为型模式
行为型模式帮助我们管理对象之间的通信和职责:
- 责任链模式:将请求沿着处理者链传递
- 命令模式:将请求封装成对象
- 解释器模式:定义语言的文法并解释
- 迭代器模式:顺序访问集合元素
- 中介者模式:封装对象间的交互
- 备忘录模式:保存和恢复对象状态
- 观察者模式:一对多的依赖关系
- 状态模式:根据状态改变行为
- 策略模式:封装可互换的算法
- 模板方法模式:定义算法骨架
- 访问者模式:在不改变元素类的前提下定义新操作
每种模式都解决了不同的行为问题,让代码更灵活、更易维护。
完整总结:23种设计模式
创建型模式(5个)
- 单例模式
- 工厂方法模式
- 抽象工厂模式
- 建造者模式
- 原型模式
结构型模式(7个)
- 适配器模式
- 桥接模式
- 组合模式
- 装饰器模式
- 外观模式
- 享元模式
- 代理模式
行为型模式(11个)
- 责任链模式
- 命令模式
- 解释器模式
- 迭代器模式
- 中介者模式
- 备忘录模式
- 观察者模式
- 状态模式
- 策略模式
- 模板方法模式
- 访问者模式
所有模式都遵循7大设计原则,帮助我们写出更好的代码!