news 2026/1/9 15:43:43

23种设计模式介绍以及C语言实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
23种设计模式介绍以及C语言实现

设计模式详解:7大原则和23种设计模式

目录

  1. 设计模式7大原则
  2. 创建型模式(5个)
  3. 结构型模式(7个)
  4. 行为型模式(11个)

设计模式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语言实现:

#include<stdio.h>#include<stdlib.h>#include<pthread.h>// 单例结构体typedefstruct{intvalue;}Singleton;// 静态变量,存储唯一实例staticSingleton*instance=NULL;staticpthread_mutex_tmutex=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);}returninstance;}/** * 设置单例的值 */voidsetSingletonValue(intvalue){Singleton*s=getSingleton();s->value=value;}/** * 获取单例的值 */intgetSingletonValue(){Singleton*s=getSingleton();returns->value;}// 测试代码intmain(){// 获取单例实例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的值也变了,说明是同一个实例return0;}

编译运行:

gcc singleton.c -o singleton -lpthread ./singleton

2. 工厂方法模式(Factory Method Pattern)

通俗解释:定义一个创建对象的接口,让子类决定实例化哪个类。就像工厂生产产品,不同工厂生产不同产品。

生活例子:

  • 汽车工厂:有"轿车工厂"、“SUV工厂”,都继承自"汽车工厂"
  • 手机工厂:有"苹果工厂"、“华为工厂”,都继承自"手机工厂"

适用场景:

  • 需要创建对象,但不确定具体类型
  • 需要扩展新的产品类型

C语言实现:

#include<stdio.h>#include<stdlib.h>// ========== 产品接口 ==========// 定义产品的抽象接口typedefstruct{void(*use)(void*self);// 使用产品的函数指针charname[50];// 产品名称}Product;// 产品使用函数(虚函数)voidproduct_use(void*self){Product*p=(Product*)self;printf("使用产品: %s\n",p->name);}// ========== 具体产品A ==========typedefstruct{Product base;// 继承ProductinttypeA_data;}ProductA;voidproductA_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;returnpa;}// ========== 具体产品B ==========typedefstruct{Product base;// 继承ProductchartypeB_data[50];}ProductB;voidproductB_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的数据");returnpb;}// ========== 工厂接口 ==========// 定义工厂的抽象接口typedefstruct{Product*(*createProduct)(void*self);// 创建产品的函数指针}Factory;// ========== 具体工厂A ==========typedefstruct{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;returnfa;}// ========== 具体工厂B ==========typedefstruct{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;returnfb;}// ========== 测试代码 ==========intmain(){// 使用工厂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);return0;}

编译运行:

gcc factory_method.c -o factory_method ./factory_method

3. 抽象工厂模式(Abstract Factory Pattern)

通俗解释:提供一个接口,用于创建相关或依赖对象的家族,而不需要指定具体类。就像家具工厂,可以生产"现代风格"或"古典风格"的整套家具。

生活例子:

  • 家具工厂:有"现代风格工厂"(生产现代沙发、现代桌子)和"古典风格工厂"(生产古典沙发、古典桌子)
  • UI主题:有"深色主题工厂"和"浅色主题工厂",分别生产深色/浅色的按钮、窗口等

适用场景:

  • 需要创建一系列相关对象
  • 需要保证产品之间的兼容性

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 产品接口:按钮 ==========typedefstruct{void(*render)(void*self);charname[50];}Button;voidbutton_render(void*self){Button*b=(Button*)self;printf("渲染按钮: %s\n",b->name);}// ========== 产品接口:窗口 ==========typedefstruct{void(*render)(void*self);charname[50];}Window;voidwindow_render(void*self){Window*w=(Window*)self;printf("渲染窗口: %s\n",w->name);}// ========== 具体产品:现代风格按钮 ==========typedefstruct{Button base;}ModernButton;voidmodernButton_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,"现代按钮");returnmb;}// ========== 具体产品:现代风格窗口 ==========typedefstruct{Window base;}ModernWindow;voidmodernWindow_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,"现代窗口");returnmw;}// ========== 具体产品:古典风格按钮 ==========typedefstruct{Button base;}ClassicButton;voidclassicButton_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,"古典按钮");returncb;}// ========== 具体产品:古典风格窗口 ==========typedefstruct{Window base;}ClassicWindow;voidclassicWindow_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,"古典窗口");returncw;}// ========== 抽象工厂接口 ==========typedefstruct{Button*(*createButton)(void*self);Window*(*createWindow)(void*self);}GUIFactory;// ========== 具体工厂:现代风格工厂 ==========typedefstruct{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;returnmf;}// ========== 具体工厂:古典风格工厂 ==========typedefstruct{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;returncf;}// ========== 客户端代码 ==========voidcreateUI(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);}intmain(){// 使用现代风格工厂ModernFactory*modernFactory=createModernFactory();createUI((GUIFactory*)modernFactory);printf("\n");// 使用古典风格工厂ClassicFactory*classicFactory=createClassicFactory();createUI((GUIFactory*)classicFactory);free(modernFactory);free(classicFactory);return0;}

编译运行:

gcc abstract_factory.c -o abstract_factory ./abstract_factory

4. 建造者模式(Builder Pattern)

通俗解释:将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。就像盖房子,有设计师、施工队,一步步建造。

生活例子:

  • 盖房子:先打地基,再建框架,再装修,最后验收
  • 点餐:选择主食、配菜、饮料、甜点,最后组成套餐

适用场景:

  • 需要创建复杂对象
  • 创建过程需要多个步骤
  • 需要不同的表示形式

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 产品:房子 ==========typedefstruct{charfoundation[50];// 地基charwalls[50];// 墙壁charroof[50];// 屋顶charinterior[50];// 内饰}House;voidprintHouse(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");}// ========== 建造者接口 ==========typedefstruct{void(*buildFoundation)(void*self,constchar*type);void(*buildWalls)(void*self,constchar*type);void(*buildRoof)(void*self,constchar*type);void(*buildInterior)(void*self,constchar*type);House*(*getHouse)(void*self);}HouseBuilder;// ========== 具体建造者:普通房子建造者 ==========typedefstruct{HouseBuilder base;House*house;}NormalHouseBuilder;voidnormalBuilder_buildFoundation(void*self,constchar*type){NormalHouseBuilder*builder=(NormalHouseBuilder*)self;strcpy(builder->house->foundation,type);printf("建造普通房子的地基: %s\n",type);}voidnormalBuilder_buildWalls(void*self,constchar*type){NormalHouseBuilder*builder=(NormalHouseBuilder*)self;strcpy(builder->house->walls,type);printf("建造普通房子的墙壁: %s\n",type);}voidnormalBuilder_buildRoof(void*self,constchar*type){NormalHouseBuilder*builder=(NormalHouseBuilder*)self;strcpy(builder->house->roof,type);printf("建造普通房子的屋顶: %s\n",type);}voidnormalBuilder_buildInterior(void*self,constchar*type){NormalHouseBuilder*builder=(NormalHouseBuilder*)self;strcpy(builder->house->interior,type);printf("建造普通房子的内饰: %s\n",type);}House*normalBuilder_getHouse(void*self){NormalHouseBuilder*builder=(NormalHouseBuilder*)self;returnbuilder->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;returnbuilder;}// ========== 具体建造者:豪华房子建造者 ==========typedefstruct{HouseBuilder base;House*house;}LuxuryHouseBuilder;voidluxuryBuilder_buildFoundation(void*self,constchar*type){LuxuryHouseBuilder*builder=(LuxuryHouseBuilder*)self;charluxury_type[100];sprintf(luxury_type,"豪华%s",type);strcpy(builder->house->foundation,luxury_type);printf("建造豪华房子的地基: %s\n",luxury_type);}voidluxuryBuilder_buildWalls(void*self,constchar*type){LuxuryHouseBuilder*builder=(LuxuryHouseBuilder*)self;charluxury_type[100];sprintf(luxury_type,"豪华%s",type);strcpy(builder->house->walls,luxury_type);printf("建造豪华房子的墙壁: %s\n",luxury_type);}voidluxuryBuilder_buildRoof(void*self,constchar*type){LuxuryHouseBuilder*builder=(LuxuryHouseBuilder*)self;charluxury_type[100];sprintf(luxury_type,"豪华%s",type);strcpy(builder->house->roof,luxury_type);printf("建造豪华房子的屋顶: %s\n",luxury_type);}voidluxuryBuilder_buildInterior(void*self,constchar*type){LuxuryHouseBuilder*builder=(LuxuryHouseBuilder*)self;charluxury_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;returnbuilder->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;returnbuilder;}// ========== 导演类:负责建造流程 ==========typedefstruct{HouseBuilder*builder;}Director;voiddirector_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;returndirector;}intmain(){// 建造普通房子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);return0;}

编译运行:

gcc builder.c -o builder ./builder

5. 原型模式(Prototype Pattern)

通俗解释:通过复制现有实例来创建新实例,而不是新建。就像复印机,可以快速复制文档。

生活例子:

  • 复印机:复制一份文档
  • 克隆:克隆羊多莉
  • 模板:用模板快速创建相似对象

适用场景:

  • 创建对象成本高(如需要大量计算或数据库查询)
  • 需要创建相似对象
  • 需要动态配置对象

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 原型接口 ==========typedefstruct{void*(*clone)(void*self);// 克隆函数void(*display)(void*self);// 显示函数charname[50];intid;}Prototype;// ========== 具体原型:简历 ==========typedefstruct{Prototype base;char*workExperience;// 工作经验intage;}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){intlen=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);returncopy;}// 显示函数voidresume_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(constchar*name,intage,constchar*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){intlen=strlen(workExp);r->workExperience=(char*)malloc(len+1);strcpy(r->workExperience,workExp);}else{r->workExperience=NULL;}returnr;}// 释放简历内存voidfreeResume(Resume*r){if(r){if(r->workExperience){free(r->workExperience);}free(r);}}// ========== 原型管理器 ==========typedefstruct{Prototype*prototypes[10];// 存储原型intcount;}PrototypeManager;PrototypeManager*createPrototypeManager(){PrototypeManager*pm=(PrototypeManager*)malloc(sizeof(PrototypeManager));pm->count=0;returnpm;}// 注册原型voidregisterPrototype(PrototypeManager*pm,Prototype*proto){if(pm->count<10){pm->prototypes[pm->count++]=proto;printf("注册原型: %s\n",proto->name);}}// 获取原型副本Prototype*getPrototype(PrototypeManager*pm,intindex){if(index>=0&&index<pm->count){returnpm->prototypes[index]->clone(pm->prototypes[index]);}returnNULL;}intmain(){// 创建原始简历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);return0;}

编译运行:

gcc prototype.c -o prototype ./prototype

总结:创建型模式

创建型模式帮助我们更灵活地创建对象:

  • 单例模式:确保只有一个实例
  • 工厂方法模式:让子类决定创建什么对象
  • 抽象工厂模式:创建一系列相关对象
  • 建造者模式:分步骤创建复杂对象
  • 原型模式:通过复制创建对象

每种模式都解决了不同的对象创建问题,选择合适的模式可以让代码更清晰、更易维护。

设计模式详解:结构型模式(7个)

结构型模式关注如何组合类和对象,形成更大的结构。


1. 适配器模式(Adapter Pattern)

通俗解释:让不兼容的接口能够一起工作。就像电源适配器,让不同国家的插头都能用。

生活例子:

  • 电源适配器:把220V电压转换成110V,让美国电器在中国能用
  • USB转HDMI:让USB接口的设备能连接HDMI显示器
  • 翻译器:让说不同语言的人能交流

适用场景:

  • 需要使用现有类,但接口不兼容
  • 需要统一多个不同接口

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 目标接口:新系统需要的接口 ==========// 这是客户端期望的接口typedefstruct{void(*request)(void*self);// 请求函数}Target;voidtarget_request(void*self){printf("目标接口:处理标准请求\n");}// ========== 被适配者:旧系统(不兼容的接口) ==========// 这是已经存在的类,但接口不兼容typedefstruct{void(*specificRequest)(void*self);// 特殊请求函数}Adaptee;voidadaptee_specificRequest(void*self){printf("被适配者:处理特殊请求(旧接口)\n");}Adaptee*createAdaptee(){Adaptee*a=(Adaptee*)malloc(sizeof(Adaptee));a->specificRequest=adaptee_specificRequest;returna;}// ========== 适配器:连接目标接口和被适配者 ==========// 适配器实现了目标接口,内部使用被适配者typedefstruct{Target base;// 继承目标接口Adaptee*adaptee;// 包含被适配者}Adapter;voidadapter_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;returnadapter;}// ========== 客户端代码 ==========voidclientCode(Target*target){printf("客户端:调用目标接口\n");target->request(target);}intmain(){printf("=== 适配器模式演示 ===\n\n");// 创建被适配者(旧系统)Adaptee*adaptee=createAdaptee();// 创建适配器,将旧系统适配到新接口Adapter*adapter=createAdapter(adaptee);// 客户端使用目标接口(新接口)// 适配器让旧系统看起来像新接口clientCode((Target*)adapter);// 释放内存free(adaptee);free(adapter);return0;}

编译运行:

gcc adapter.c -o adapter ./adapter

2. 桥接模式(Bridge Pattern)

通俗解释:将抽象和实现分离,使它们可以独立变化。就像遥控器和电视,遥控器(抽象)可以控制不同品牌的电视(实现)。

生活例子:

  • 遥控器和电视:遥控器是抽象,不同品牌电视是实现
  • 画笔和颜色:画笔是抽象,不同颜色是实现
  • 操作系统和驱动程序:操作系统是抽象,不同硬件驱动是实现

适用场景:

  • 需要在运行时切换实现
  • 需要避免抽象和实现的绑定

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 实现接口:颜色(实现部分) ==========// 这是实现部分的抽象typedefstruct{void(*applyColor)(void*self);// 应用颜色charcolorName[50];}Color;voidcolor_applyColor(void*self){Color*c=(Color*)self;printf("应用颜色: %s\n",c->colorName);}// ========== 具体实现:红色 ==========typedefstruct{Color base;}RedColor;voidredColor_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,"红色");returnrc;}// ========== 具体实现:蓝色 ==========typedefstruct{Color base;}BlueColor;voidblueColor_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,"蓝色");returnbc;}// ========== 抽象类:形状(抽象部分) ==========// 这是抽象部分,包含对实现的引用typedefstruct{Color*color;// 桥接:持有实现部分的引用void(*draw)(void*self);// 绘制函数}Shape;voidshape_draw(void*self){Shape*s=(Shape*)self;printf("绘制形状");if(s->color){printf(",使用");s->color->applyColor(s->color);}}// ========== 具体抽象:圆形 ==========typedefstruct{Shape base;}Circle;voidcircle_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;returncircle;}// ========== 具体抽象:方形 ==========typedefstruct{Shape base;}Square;voidsquare_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;returnsquare;}intmain(){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);return0;}

编译运行:

gcc bridge.c -o bridge ./bridge

3. 组合模式(Composite Pattern)

通俗解释:将对象组合成树形结构,使单个对象和组合对象使用一致。就像文件夹和文件,文件夹可以包含文件,也可以包含其他文件夹。

生活例子:

  • 文件系统:文件夹可以包含文件或子文件夹
  • 组织结构:部门可以包含员工或子部门
  • 菜单系统:菜单可以包含菜单项或子菜单

适用场景:

  • 需要表示部分-整体层次结构
  • 需要统一处理单个对象和组合对象

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 组件接口 ==========// 这是组合模式的核心接口,既可以表示叶子节点,也可以表示组合节点typedefstructComponent{charname[100];void(*operation)(structComponent*self);// 操作函数void(*add)(structComponent*self,structComponent*child);// 添加子组件void(*remove)(structComponent*self,structComponent*child);// 移除子组件structComponent*(*getChild)(structComponent*self,intindex);// 获取子组件}Component;// ========== 叶子节点:文件 ==========// 叶子节点没有子节点typedefstruct{Component base;intsize;// 文件大小}File;voidfile_operation(Component*self){File*f=(File*)self;printf("文件: %s (大小: %d KB)\n",f->base.name,f->size);}voidfile_add(Component*self,Component*child){printf("错误:文件不能添加子组件\n");}voidfile_remove(Component*self,Component*child){printf("错误:文件不能移除子组件\n");}Component*file_getChild(Component*self,intindex){returnNULL;// 文件没有子节点}File*createFile(constchar*name,intsize){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;returnf;}// ========== 组合节点:文件夹 ==========// 组合节点可以包含子组件typedefstruct{Component base;Component*children[100];// 子组件数组intchildCount;// 子组件数量}Folder;voidfolder_operation(Component*self){Folder*folder=(Folder*)self;printf("文件夹: %s (包含 %d 个项目)\n",folder->base.name,folder->childCount);// 递归操作所有子组件for(inti=0;i<folder->childCount;i++){printf(" ");folder->children[i]->operation(folder->children[i]);}}voidfolder_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);}}voidfolder_remove(Component*self,Component*child){Folder*folder=(Folder*)self;for(inti=0;i<folder->childCount;i++){if(folder->children[i]==child){// 移除子组件for(intj=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,intindex){Folder*folder=(Folder*)self;if(index>=0&&index<folder->childCount){returnfolder->children[index];}returnNULL;}Folder*createFolder(constchar*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;returnfolder;}intmain(){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);return0;}

编译运行:

gcc composite.c -o composite ./composite

4. 装饰器模式(Decorator Pattern)

通俗解释:动态地给对象添加新功能,比继承更灵活。就像给手机加保护壳、贴膜、挂件,一层层装饰。

生活例子:

  • 手机装饰:手机 + 保护壳 + 贴膜 + 挂件
  • 咖啡:咖啡 + 糖 + 牛奶 + 奶油
  • 披萨:基础披萨 + 芝士 + 香肠 + 蔬菜

适用场景:

  • 需要动态添加功能
  • 不想使用继承扩展功能

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 组件接口:咖啡 ==========typedefstruct{chardescription[100];int(*cost)(void*self);// 计算价格void(*getDescription)(void*self,char*buffer);// 获取描述}Coffee;intcoffee_cost(void*self){return0;}voidcoffee_getDescription(void*self,char*buffer){Coffee*c=(Coffee*)self;strcpy(buffer,c->description);}// ========== 具体组件:基础咖啡 ==========typedefstruct{Coffee base;}SimpleCoffee;intsimpleCoffee_cost(void*self){return10;// 基础咖啡10元}voidsimpleCoffee_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;returnsc;}// ========== 装饰器基类 ==========typedefstruct{Coffee base;Coffee*coffee;// 被装饰的咖啡}CoffeeDecorator;// ========== 具体装饰器:加糖 ==========typedefstruct{CoffeeDecorator base;}SugarDecorator;intsugarDecorator_cost(void*self){SugarDecorator*sd=(SugarDecorator*)self;returnsd->base.coffee->cost(sd->base.coffee)+2;// 加2元}voidsugarDecorator_getDescription(void*self,char*buffer){SugarDecorator*sd=(SugarDecorator*)self;chartemp[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;returnsd;}// ========== 具体装饰器:加牛奶 ==========typedefstruct{CoffeeDecorator base;}MilkDecorator;intmilkDecorator_cost(void*self){MilkDecorator*md=(MilkDecorator*)self;returnmd->base.coffee->cost(md->base.coffee)+3;// 加3元}voidmilkDecorator_getDescription(void*self,char*buffer){MilkDecorator*md=(MilkDecorator*)self;chartemp[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;returnmd;}// ========== 具体装饰器:加奶油 ==========typedefstruct{CoffeeDecorator base;}CreamDecorator;intcreamDecorator_cost(void*self){CreamDecorator*cd=(CreamDecorator*)self;returncd->base.coffee->cost(cd->base.coffee)+4;// 加4元}voidcreamDecorator_getDescription(void*self,char*buffer){CreamDecorator*cd=(CreamDecorator*)self;chartemp[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;returncd;}intmain(){printf("=== 装饰器模式演示 ===\n\n");// 创建基础咖啡SimpleCoffee*coffee=createSimpleCoffee();chardesc[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);return0;}

编译运行:

gcc decorator.c -o decorator ./decorator

5. 外观模式(Facade Pattern)

通俗解释:为复杂子系统提供一个简单接口。就像一键启动电脑,不需要知道CPU、内存、硬盘如何协调工作。

生活例子:

  • 一键启动:一键启动电脑,隐藏了复杂的启动过程
  • 银行ATM:简单的界面,背后是复杂的银行系统
  • 智能家居:一个APP控制所有设备,隐藏了复杂的通信协议

适用场景:

  • 需要简化复杂子系统
  • 需要解耦客户端和子系统

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 子系统1:CPU ==========typedefstruct{void(*start)(void);void(*stop)(void);}CPU;voidcpu_start(void){printf("CPU: 启动\n");}voidcpu_stop(void){printf("CPU: 停止\n");}CPU*createCPU(){CPU*cpu=(CPU*)malloc(sizeof(CPU));cpu->start=cpu_start;cpu->stop=cpu_stop;returncpu;}// ========== 子系统2:内存 ==========typedefstruct{void(*load)(void);void(*unload)(void);}Memory;voidmemory_load(void){printf("内存: 加载数据\n");}voidmemory_unload(void){printf("内存: 卸载数据\n");}Memory*createMemory(){Memory*mem=(Memory*)malloc(sizeof(Memory));mem->load=memory_load;mem->unload=memory_unload;returnmem;}// ========== 子系统3:硬盘 ==========typedefstruct{void(*read)(void);void(*write)(void);}HardDrive;voidhardDrive_read(void){printf("硬盘: 读取数据\n");}voidhardDrive_write(void){printf("硬盘: 写入数据\n");}HardDrive*createHardDrive(){HardDrive*hd=(HardDrive*)malloc(sizeof(HardDrive));hd->read=hardDrive_read;hd->write=hardDrive_write;returnhd;}// ========== 外观类:计算机 ==========// 外观类封装了子系统的复杂操作,提供简单接口typedefstruct{CPU*cpu;Memory*memory;HardDrive*hardDrive;void(*startComputer)(void*self);void(*stopComputer)(void*self);}Computer;voidcomputer_startComputer(void*self){Computer*comp=(Computer*)self;printf("=== 启动计算机 ===\n");comp->cpu->start();comp->memory->load();comp->hardDrive->read();printf("计算机启动完成!\n\n");}voidcomputer_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;returncomp;}voidfreeComputer(Computer*comp){if(comp){free(comp->cpu);free(comp->memory);free(comp->hardDrive);free(comp);}}intmain(){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);return0;}

编译运行:

gcc facade.c -o facade ./facade

6. 享元模式(Flyweight Pattern)

通俗解释:通过共享相同数据来减少内存使用。就像图书馆,多个人可以共享同一本书,而不需要每人买一本。

生活例子:

  • 图书馆:多个人共享同一本书
  • 字体:多个字符共享同一字体对象
  • 游戏:多个敌人共享同一模型和纹理

适用场景:

  • 需要创建大量相似对象
  • 对象的大部分状态可以共享

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 享元接口:字符 ==========typedefstruct{charsymbol;// 字符(内部状态,可共享)void(*display)(void*self,intx,inty);// 显示函数}Character;// ========== 具体享元:具体字符 ==========typedefstruct{Character base;charfont[50];// 字体(内部状态,可共享)intsize;// 大小(内部状态,可共享)}ConcreteCharacter;voidcharacter_display(void*self,intx,inty){ConcreteCharacter*cc=(ConcreteCharacter*)self;printf("显示字符 '%c' (字体: %s, 大小: %d) 在位置 (%d, %d)\n",cc->base.symbol,cc->font,cc->size,x,y);}ConcreteCharacter*createCharacter(charsymbol,constchar*font,intsize){ConcreteCharacter*cc=(ConcreteCharacter*)malloc(sizeof(ConcreteCharacter));cc->base.symbol=symbol;strcpy(cc->font,font);cc->size=size;cc->base.display=character_display;returncc;}// ========== 享元工厂:管理享元对象 ==========typedefstruct{ConcreteCharacter*characters[100];// 享元对象池intcount;}CharacterFactory;CharacterFactory*createCharacterFactory(){CharacterFactory*factory=(CharacterFactory*)malloc(sizeof(CharacterFactory));factory->count=0;returnfactory;}// 获取享元对象(如果不存在则创建)ConcreteCharacter*getCharacter(CharacterFactory*factory,charsymbol,constchar*font,intsize){// 查找是否已存在相同的享元对象for(inti=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);returncc;// 返回已存在的对象}}// 不存在,创建新的享元对象printf("创建新享元对象: '%c'\n",symbol);ConcreteCharacter*cc=createCharacter(symbol,font,size);factory->characters[factory->count++]=cc;returncc;}// ========== 外部状态:位置信息 ==========// 这些是外部状态,不存储在享元对象中typedefstruct{Character*character;// 享元对象引用intx;// 外部状态:X坐标inty;// 外部状态:Y坐标}CharacterContext;CharacterContext*createCharacterContext(Character*ch,intx,inty){CharacterContext*ctx=(CharacterContext*)malloc(sizeof(CharacterContext));ctx->character=ch;ctx->x=x;ctx->y=y;returnctx;}voiddisplayContext(CharacterContext*ctx){ctx->character->display(ctx->character,ctx->x,ctx->y);}intmain(){printf("=== 享元模式演示 ===\n\n");// 创建享元工厂CharacterFactory*factory=createCharacterFactory();// 创建字符上下文(包含外部状态)printf("--- 创建文本 ---\n");CharacterContext*contexts[10];intcontextCount=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(inti=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(inti=0;i<contextCount;i++){free(contexts[i]);}for(inti=0;i<factory->count;i++){free(factory->characters[i]);}free(factory);return0;}

编译运行:

gcc flyweight.c -o flyweight ./flyweight

7. 代理模式(Proxy Pattern)

通俗解释:为其他对象提供代理以控制对这个对象的访问。就像代购,你通过代购买东西,代购控制你和商家的交互。

生活例子:

  • 代购:代购代理你购买商品
  • 门禁卡:门禁卡代理你开门
  • 缓存代理:缓存代理数据库,减少数据库访问

适用场景:

  • 需要控制对象访问
  • 需要延迟加载
  • 需要添加额外功能(如缓存、日志)

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>// 用于sleep函数// ========== 主题接口:图像 ==========typedefstruct{void(*display)(void*self);// 显示函数charfilename[100];}Image;voidimage_display(void*self){Image*img=(Image*)self;printf("显示图像: %s\n",img->filename);}// ========== 真实主题:真实图像 ==========// 这是实际的对象,可能创建成本很高typedefstruct{Image base;}RealImage;voidrealImage_display(void*self){RealImage*ri=(RealImage*)self;printf("从磁盘加载图像: %s\n",ri->base.filename);sleep(1);// 模拟加载时间printf("显示真实图像: %s\n",ri->base.filename);}RealImage*createRealImage(constchar*filename){RealImage*ri=(RealImage*)malloc(sizeof(RealImage));strcpy(ri->base.filename,filename);ri->base.display=realImage_display;printf("创建真实图像对象: %s\n",filename);returnri;}// ========== 代理:图像代理 ==========// 代理控制对真实图像的访问typedefstruct{Image base;RealImage*realImage;// 真实图像的引用intloaded;// 是否已加载}ProxyImage;voidproxyImage_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(constchar*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);returnproxy;}intmain(){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);return0;}

编译运行:

gcc proxy.c -o proxy ./proxy

总结:结构型模式

结构型模式帮助我们组合类和对象,形成更大的结构:

  • 适配器模式:让不兼容的接口能够一起工作
  • 桥接模式:将抽象和实现分离
  • 组合模式:统一处理单个对象和组合对象
  • 装饰器模式:动态添加功能
  • 外观模式:简化复杂子系统
  • 享元模式:共享数据减少内存
  • 代理模式:控制对象访问

每种模式都解决了不同的结构问题,让代码更灵活、更易维护。

设计模式详解:行为型模式(11个)

行为型模式关注对象之间的通信和职责分配。


1. 责任链模式(Chain of Responsibility Pattern)

通俗解释:将请求沿着处理者链传递,直到有处理者处理它。就像请假,先找组长,组长处理不了找经理,经理处理不了找总经理。

生活例子:

  • 请假流程:员工 → 组长 → 经理 → 总经理
  • 客服系统:一级客服 → 二级客服 → 三级客服
  • 异常处理:try-catch链式处理

适用场景:

  • 有多个对象可以处理请求
  • 不确定哪个对象处理请求
  • 需要动态指定处理者

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 请求类型 ==========typedefstruct{intamount;// 金额chartype[50];// 类型}Request;Request*createRequest(intamount,constchar*type){Request*req=(Request*)malloc(sizeof(Request));req->amount=amount;strcpy(req->type,type);returnreq;}// ========== 处理者接口 ==========typedefstructHandler{structHandler*next;// 下一个处理者intlimit;// 处理权限上限charname[50];// 处理者名称int(*handle)(structHandler*self,Request*request);// 处理函数void(*setNext)(structHandler*self,structHandler*next);// 设置下一个处理者}Handler;// 设置下一个处理者voidhandler_setNext(Handler*self,Handler*next){self->next=next;}// 处理请求(模板方法)inthandler_handle(Handler*self,Request*request){// 如果当前处理者可以处理if(request->amount<=self->limit){printf("%s 处理了请求: %s, 金额: %d\n",self->name,request->type,request->amount);return1;// 处理成功}// 如果不能处理,传递给下一个处理者if(self->next!=NULL){printf("%s 无法处理,传递给下一个处理者\n",self->name);returnself->next->handle(self->next,request);}// 没有处理者能处理printf("没有处理者能处理该请求\n");return0;}// ========== 具体处理者:组长 ==========typedefstruct{Handler base;}GroupLeader;intgroupLeader_handle(Handler*self,Request*request){self->limit=1000;// 组长最多处理1000元strcpy(self->name,"组长");returnhandler_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;returngl;}// ========== 具体处理者:经理 ==========typedefstruct{Handler base;}Manager;intmanager_handle(Handler*self,Request*request){self->limit=5000;// 经理最多处理5000元strcpy(self->name,"经理");returnhandler_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;returnm;}// ========== 具体处理者:总经理 ==========typedefstruct{Handler base;}GeneralManager;intgeneralManager_handle(Handler*self,Request*request){self->limit=50000;// 总经理最多处理50000元strcpy(self->name,"总经理");returnhandler_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;returngm;}intmain(){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);return0;}

编译运行:

gcc chain_of_responsibility.c -o chain_of_responsibility ./chain_of_responsibility

2. 命令模式(Command Pattern)

通俗解释:将请求封装成对象,从而可以用不同的请求对客户进行参数化。就像遥控器,每个按钮都是一个命令对象。

生活例子:

  • 遥控器:每个按钮是一个命令,可以控制电视
  • 菜单:每个菜单项是一个命令
  • 撤销/重做:命令可以保存,支持撤销和重做

适用场景:

  • 需要将请求参数化
  • 需要支持撤销/重做
  • 需要记录请求日志

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 接收者:电视 ==========// 这是实际执行操作的对象typedefstruct{intvolume;// 音量intchannel;// 频道intisOn;// 是否开机}TV;TV*createTV(){TV*tv=(TV*)malloc(sizeof(TV));tv->volume=50;tv->channel=1;tv->isOn=0;returntv;}voidtv_turnOn(TV*tv){tv->isOn=1;printf("电视已开机\n");}voidtv_turnOff(TV*tv){tv->isOn=0;printf("电视已关机\n");}voidtv_setVolume(TV*tv,intvolume){tv->volume=volume;printf("设置音量为: %d\n",volume);}voidtv_setChannel(TV*tv,intchannel){tv->channel=channel;printf("设置频道为: %d\n",channel);}voidtv_showStatus(TV*tv){printf("=== 电视状态 ===\n");printf("状态: %s\n",tv->isOn?"开机":"关机");printf("音量: %d\n",tv->volume);printf("频道: %d\n",tv->channel);printf("==============\n");}// ========== 命令接口 ==========typedefstruct{void(*execute)(void*self);// 执行命令void(*undo)(void*self);// 撤销命令chardescription[100];// 命令描述}Command;// ========== 具体命令:开机命令 ==========typedefstruct{Command base;TV*tv;intpreviousState;// 保存之前的状态,用于撤销}TurnOnCommand;voidturnOnCommand_execute(void*self){TurnOnCommand*cmd=(TurnOnCommand*)self;cmd->previousState=cmd->tv->isOn;tv_turnOn(cmd->tv);}voidturnOnCommand_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;returncmd;}// ========== 具体命令:关机命令 ==========typedefstruct{Command base;TV*tv;intpreviousState;}TurnOffCommand;voidturnOffCommand_execute(void*self){TurnOffCommand*cmd=(TurnOffCommand*)self;cmd->previousState=cmd->tv->isOn;tv_turnOff(cmd->tv);}voidturnOffCommand_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;returncmd;}// ========== 具体命令:设置音量命令 ==========typedefstruct{Command base;TV*tv;intvolume;intpreviousVolume;}SetVolumeCommand;voidsetVolumeCommand_execute(void*self){SetVolumeCommand*cmd=(SetVolumeCommand*)self;cmd->previousVolume=cmd->tv->volume;tv_setVolume(cmd->tv,cmd->volume);}voidsetVolumeCommand_undo(void*self){SetVolumeCommand*cmd=(SetVolumeCommand*)self;tv_setVolume(cmd->tv,cmd->previousVolume);}SetVolumeCommand*createSetVolumeCommand(TV*tv,intvolume){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;returncmd;}// ========== 调用者:遥控器 ==========// 这是发送命令的对象typedefstruct{Command*command;// 当前命令Command*history[100];// 命令历史(用于撤销)inthistoryCount;}RemoteControl;RemoteControl*createRemoteControl(){RemoteControl*rc=(RemoteControl*)malloc(sizeof(RemoteControl));rc->command=NULL;rc->historyCount=0;returnrc;}voidremoteControl_setCommand(RemoteControl*rc,Command*cmd){rc->command=cmd;}voidremoteControl_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;}}}voidremoteControl_undo(RemoteControl*rc){if(rc->historyCount>0){Command*lastCmd=rc->history[--rc->historyCount];printf("撤销命令: %s\n",lastCmd->description);lastCmd->undo(lastCmd);}else{printf("没有可撤销的命令\n");}}intmain(){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);return0;}

编译运行:

gcc command.c -ocommand./command

3. 解释器模式(Interpreter Pattern)

通俗解释:定义语言的文法,并解释该语言中的句子。就像编译器,解释代码的含义。

生活例子:

  • 计算器:解释数学表达式
  • 正则表达式:解释匹配规则
  • SQL解释器:解释SQL语句

适用场景:

  • 需要解释特定语言
  • 语法简单,性能要求不高

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>#include<ctype.h>// ========== 表达式接口 ==========typedefstruct{int(*interpret)(void*self);// 解释函数}Expression;// ========== 终结符表达式:数字 ==========typedefstruct{Expression base;intvalue;}NumberExpression;intnumberExpression_interpret(void*self){NumberExpression*ne=(NumberExpression*)self;returnne->value;}NumberExpression*createNumberExpression(intvalue){NumberExpression*ne=(NumberExpression*)malloc(sizeof(NumberExpression));ne->base.interpret=numberExpression_interpret;ne->value=value;returnne;}// ========== 非终结符表达式:加法 ==========typedefstruct{Expression base;Expression*left;// 左表达式Expression*right;// 右表达式}AddExpression;intaddExpression_interpret(void*self){AddExpression*ae=(AddExpression*)self;intleftValue=ae->left->interpret(ae->left);intrightValue=ae->right->interpret(ae->right);returnleftValue+rightValue;}AddExpression*createAddExpression(Expression*left,Expression*right){AddExpression*ae=(AddExpression*)malloc(sizeof(AddExpression));ae->base.interpret=addExpression_interpret;ae->left=left;ae->right=right;returnae;}// ========== 非终结符表达式:减法 ==========typedefstruct{Expression base;Expression*left;Expression*right;}SubtractExpression;intsubtractExpression_interpret(void*self){SubtractExpression*se=(SubtractExpression*)self;intleftValue=se->left->interpret(se->left);intrightValue=se->right->interpret(se->right);returnleftValue-rightValue;}SubtractExpression*createSubtractExpression(Expression*left,Expression*right){SubtractExpression*se=(SubtractExpression*)malloc(sizeof(SubtractExpression));se->base.interpret=subtractExpression_interpret;se->left=left;se->right=right;returnse;}// ========== 非终结符表达式:乘法 ==========typedefstruct{Expression base;Expression*left;Expression*right;}MultiplyExpression;intmultiplyExpression_interpret(void*self){MultiplyExpression*me=(MultiplyExpression*)self;intleftValue=me->left->interpret(me->left);intrightValue=me->right->interpret(me->right);returnleftValue*rightValue;}MultiplyExpression*createMultiplyExpression(Expression*left,Expression*right){MultiplyExpression*me=(MultiplyExpression*)malloc(sizeof(MultiplyExpression));me->base.interpret=multiplyExpression_interpret;me->left=left;me->right=right;returnme;}// ========== 上下文:解析器 ==========// 简化版解析器,解析 "数字 运算符 数字" 格式Expression*parseExpression(constchar*expr){// 这里简化处理,实际应该用更复杂的解析器// 示例:解析 "5 + 3" 或 "10 - 2" 或 "4 * 2"intnum1=0,num2=0;charop='+';// 简单解析(实际应该用词法分析器和语法分析器)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:returnleft;}}intmain(){printf("=== 解释器模式演示 ===\n\n");// 创建表达式:5 + 3Expression*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 - 2Expression*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 * 2Expression*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) * 2Expression*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);return0;}

编译运行:

gcc interpreter.c -o interpreter ./interpreter

4. 迭代器模式(Iterator Pattern)

通俗解释:提供一种方法顺序访问一个聚合对象中的各个元素,而不暴露其内部表示。就像遥控器,可以顺序切换电视频道。

生活例子:

  • 遥控器:顺序切换频道
  • 书签:顺序浏览网页
  • 播放列表:顺序播放歌曲

适用场景:

  • 需要遍历集合
  • 需要统一遍历接口

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 迭代器接口 ==========typedefstruct{int(*hasNext)(void*self);// 是否有下一个元素void*(*next)(void*self);// 获取下一个元素void(*reset)(void*self);// 重置迭代器}Iterator;// ========== 聚合接口 ==========typedefstruct{Iterator*(*createIterator)(void*self);// 创建迭代器intsize;// 集合大小}Aggregate;// ========== 具体聚合:数组集合 ==========typedefstruct{Aggregate base;int*data;// 数据数组intcapacity;// 容量}ArrayCollection;// ========== 具体迭代器:数组迭代器 ==========typedefstruct{Iterator base;ArrayCollection*collection;// 关联的集合intcurrentIndex;// 当前索引}ArrayIterator;intarrayIterator_hasNext(void*self){ArrayIterator*it=(ArrayIterator*)self;returnit->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++];returnitem;}returnNULL;}voidarrayIterator_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;returnarrayIterator_create(ac);}ArrayCollection*createArrayCollection(intcapacity){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;returnac;}voidarrayCollection_add(ArrayCollection*ac,intvalue){if(ac->base.size<ac->capacity){ac->data[ac->base.size++]=value;}}// ========== 客户端代码 ==========voidtraverseCollection(Aggregate*aggregate){printf("遍历集合:\n");Iterator*it=aggregate->createIterator(aggregate);intindex=0;while(it->hasNext(it)){int*value=(int*)it->next(it);printf(" 元素[%d]: %d\n",index++,*value);}free(it);}intmain(){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);return0;}

编译运行:

gcc iterator.c -o iterator ./iterator

5. 中介者模式(Mediator Pattern)

通俗解释:用一个中介对象来封装一系列对象的交互。就像聊天室,所有人通过聊天室交流,而不是直接互相联系。

生活例子:

  • 聊天室:所有人通过聊天室交流
  • 机场塔台:所有飞机通过塔台协调
  • 股票交易所:所有交易通过交易所进行

适用场景:

  • 对象之间有很多交互
  • 需要解耦对象之间的直接依赖

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 中介者接口 ==========typedefstructMediator{void(*sendMessage)(structMediator*self,constchar*from,constchar*to,constchar*message);}Mediator;// ========== 同事接口 ==========typedefstructColleague{charname[50];Mediator*mediator;// 中介者引用void(*send)(structColleague*self,constchar*to,constchar*message);void(*receive)(structColleague*self,constchar*from,constchar*message);}Colleague;voidcolleague_send(Colleague*self,constchar*to,constchar*message){printf("%s 发送消息给 %s: %s\n",self->name,to,message);self->mediator->sendMessage(self->mediator,self->name,to,message);}voidcolleague_receive(Colleague*self,constchar*from,constchar*message){printf("%s 收到来自 %s 的消息: %s\n",self->name,from,message);}// ========== 具体中介者:聊天室 ==========typedefstruct{Mediator base;Colleague*colleagues[10];// 注册的同事intcount;}ChatRoom;voidchatRoom_sendMessage(Mediator*self,constchar*from,constchar*to,constchar*message){ChatRoom*cr=(ChatRoom*)self;// 查找接收者for(inti=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(inti=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;returncr;}voidchatRoom_register(ChatRoom*cr,Colleague*colleague){if(cr->count<10){cr->colleagues[cr->count++]=colleague;colleague->mediator=(Mediator*)cr;printf("%s 加入聊天室\n",colleague->name);}}// ========== 具体同事:用户 ==========typedefstruct{Colleague base;}User;User*createUser(constchar*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;returnuser;}intmain(){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);return0;}

编译运行:

gcc mediator.c -o mediator ./mediator

6. 备忘录模式(Memento Pattern)

通俗解释:在不破坏封装性的前提下,捕获对象的内部状态,并在对象之外保存这个状态。就像游戏存档,可以保存和恢复游戏状态。

生活例子:

  • 游戏存档:保存游戏状态,可以恢复
  • 撤销功能:保存操作历史,可以撤销
  • 数据库事务:保存事务状态,可以回滚

适用场景:

  • 需要保存对象状态
  • 需要支持撤销功能

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 备忘录:保存状态 ==========typedefstruct{intlevel;// 关卡intscore;// 分数inthealth;// 生命值charstate[100];// 状态描述}Memento;Memento*createMemento(intlevel,intscore,inthealth,constchar*state){Memento*m=(Memento*)malloc(sizeof(Memento));m->level=level;m->score=score;m->health=health;strcpy(m->state,state);returnm;}voidmemento_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");}// ========== 原发器:游戏角色 ==========// 需要保存状态的对象typedefstruct{intlevel;intscore;inthealth;charstate[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);returncreateMemento(gc->level,gc->score,gc->health,gc->state);}voidgameCharacter_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");}voidgameCharacter_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");}voidgameCharacter_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;returngc;}// ========== 管理者:存档管理器 ==========// 负责保存和管理备忘录typedefstruct{Memento*mementos[10];// 存档列表intcount;}Caretaker;Caretaker*createCaretaker(){Caretaker*ct=(Caretaker*)malloc(sizeof(Caretaker));ct->count=0;returnct;}voidcaretaker_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,intindex){if(index>=1&&index<=ct->count){printf("加载存档%d\n",index);returnct->mementos[index-1];}printf("存档不存在\n");returnNULL;}intmain(){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);// 恢复存档1printf("\n--- 恢复到存档1 ---\n");Memento*loaded=caretaker_load(caretaker,1);if(loaded){memento_display(loaded);character->restore(character,loaded);character->display(character);}// 释放内存(简化版)free(character);for(inti=0;i<caretaker->count;i++){free(caretaker->mementos[i]);}free(caretaker);return0;}

编译运行:

gcc memento.c -o memento ./memento

7. 观察者模式(Observer Pattern)

通俗解释:定义对象间一对多的依赖关系,当一个对象状态改变时,所有依赖它的对象都会收到通知。就像订阅报纸,报纸更新时,所有订阅者都会收到。

生活例子:

  • 订阅报纸:报纸更新,订阅者收到
  • 微信朋友圈:发朋友圈,好友收到通知
  • 股票价格:价格变化,所有关注者收到通知

适用场景:

  • 一个对象状态改变需要通知多个对象
  • 需要解耦观察者和被观察者

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 观察者接口 ==========typedefstructObserver{charname[50];void(*update)(structObserver*self,constchar*message);// 更新函数}Observer;// ========== 主题接口 ==========typedefstructSubject{Observer*observers[10];// 观察者列表intobserverCount;// 观察者数量void(*attach)(structSubject*self,Observer*observer);// 添加观察者void(*detach)(structSubject*self,Observer*observer);// 移除观察者void(*notify)(structSubject*self,constchar*message);// 通知观察者}Subject;voidsubject_attach(Subject*self,Observer*observer){if(self->observerCount<10){self->observers[self->observerCount++]=observer;printf("%s 订阅了主题\n",observer->name);}}voidsubject_detach(Subject*self,Observer*observer){for(inti=0;i<self->observerCount;i++){if(self->observers[i]==observer){// 移除观察者for(intj=i;j<self->observerCount-1;j++){self->observers[j]=self->observers[j+1];}self->observerCount--;printf("%s 取消订阅\n",observer->name);return;}}}voidsubject_notify(Subject*self,constchar*message){printf("\n--- 通知所有观察者 ---\n");for(inti=0;i<self->observerCount;i++){self->observers[i]->update(self->observers[i],message);}}// ========== 具体主题:新闻发布者 ==========typedefstruct{Subject base;charnews[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,"");returnnp;}voidnewsPublisher_publish(NewsPublisher*np,constchar*news){strcpy(np->news,news);printf("发布新闻: %s\n",news);np->base.notify(&np->base,news);}// ========== 具体观察者:订阅者 ==========typedefstruct{Observer base;}NewsSubscriber;voidnewsSubscriber_update(Observer*self,constchar*message){printf("%s 收到新闻: %s\n",self->name,message);}NewsSubscriber*createNewsSubscriber(constchar*name){NewsSubscriber*ns=(NewsSubscriber*)malloc(sizeof(NewsSubscriber));strcpy(ns->base.name,name);ns->base.update=newsSubscriber_update;returnns;}intmain(){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);return0;}

编译运行:

gcc observer.c -o observer ./observer

8. 状态模式(State Pattern)

通俗解释:允许对象在内部状态改变时改变它的行为。就像自动售货机,不同状态(有货/无货)有不同的行为。

生活例子:

  • 自动售货机:有货/无货状态,行为不同
  • 交通灯:红灯/绿灯/黄灯状态
  • 游戏角色:正常/受伤/死亡状态

适用场景:

  • 对象行为依赖于状态
  • 需要根据状态改变行为

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 状态接口 ==========typedefstructState{void(*handle)(void*self);// 处理函数charname[50];}State;// ========== 上下文:自动售货机 ==========typedefstruct{State*currentState;// 当前状态intitemCount;// 商品数量void(*request)(void*self);// 请求操作void(*setState)(void*self,State*state);// 设置状态}VendingMachine;voidvendingMachine_request(void*self){VendingMachine*vm=(VendingMachine*)self;printf("当前状态: %s\n",vm->currentState->name);vm->currentState->handle(vm->currentState);}voidvendingMachine_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;returnvm;}// ========== 具体状态:有货状态 ==========typedefstruct{State base;VendingMachine*machine;}HasItemState;voidhasItemState_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;returnstate;}// ========== 具体状态:无货状态 ==========typedefstruct{State base;VendingMachine*machine;}NoItemState;voidnoItemState_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;returnstate;}intmain(){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);return0;}

编译运行:

gcc state.c -o state ./state

9. 策略模式(Strategy Pattern)

通俗解释:定义一系列算法,把它们封装起来,并且使它们可以互换。就像支付方式,可以用支付宝、微信、信用卡等不同策略。

生活例子:

  • 支付方式:支付宝、微信、信用卡等不同策略
  • 排序算法:快速排序、冒泡排序、归并排序等
  • 导航方式:步行、开车、公交等不同路线策略

适用场景:

  • 需要在运行时选择算法
  • 有多个相似的类,只是行为不同

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 策略接口:支付策略 ==========typedefstruct{void(*pay)(void*self,doubleamount);// 支付函数charname[50];}PaymentStrategy;// ========== 具体策略:支付宝支付 ==========typedefstruct{PaymentStrategy base;}AlipayStrategy;voidalipayStrategy_pay(void*self,doubleamount){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;returnstrategy;}// ========== 具体策略:微信支付 ==========typedefstruct{PaymentStrategy base;}WeChatStrategy;voidweChatStrategy_pay(void*self,doubleamount){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;returnstrategy;}// ========== 具体策略:信用卡支付 ==========typedefstruct{PaymentStrategy base;}CreditCardStrategy;voidcreditCardStrategy_pay(void*self,doubleamount){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;returnstrategy;}// ========== 上下文:购物车 ==========typedefstruct{PaymentStrategy*strategy;// 当前支付策略doubletotal;// 总金额void(*setPaymentStrategy)(void*self,PaymentStrategy*strategy);// 设置支付策略void(*checkout)(void*self);// 结账void(*addItem)(void*self,doubleprice);// 添加商品}ShoppingCart;voidshoppingCart_setPaymentStrategy(void*self,PaymentStrategy*strategy){ShoppingCart*cart=(ShoppingCart*)self;cart->strategy=strategy;printf("设置支付方式为: %s\n",strategy->name);}voidshoppingCart_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");}voidshoppingCart_addItem(void*self,doubleprice){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;returncart;}intmain(){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);return0;}

编译运行:

gcc strategy.c -o strategy ./strategy

10. 模板方法模式(Template Method Pattern)

通俗解释:定义一个操作中算法的骨架,而将一些步骤延迟到子类中。就像做菜,步骤固定(洗菜、切菜、炒菜),但具体做法可以不同。

生活例子:

  • 做菜:步骤固定,但具体做法不同
  • 考试:流程固定(发卷、答题、收卷),但题目不同
  • 银行开户:流程固定,但不同银行细节不同

适用场景:

  • 有多个类有相似的算法结构
  • 需要控制算法的流程

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 抽象类:饮料制作模板 ==========typedefstruct{void(*brew)(void*self);// 冲泡(抽象方法)void(*addCondiments)(void*self);// 添加调料(抽象方法)void(*makeBeverage)(void*self);// 制作饮料(模板方法)}BeverageTemplate;// 模板方法:定义算法骨架voidbeverageTemplate_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");}// ========== 具体类:咖啡 ==========typedefstruct{BeverageTemplate base;}Coffee;voidcoffee_brew(void*self){printf("冲泡咖啡\n");}voidcoffee_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;returncoffee;}// ========== 具体类:茶 ==========typedefstruct{BeverageTemplate base;}Tea;voidtea_brew(void*self){printf("冲泡茶叶\n");}voidtea_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;returntea;}// ========== 具体类:纯咖啡(不添加调料) ==========typedefstruct{BeverageTemplate base;}BlackCoffee;voidblackCoffee_brew(void*self){printf("冲泡咖啡\n");}voidblackCoffee_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;returnbc;}intmain(){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);return0;}

编译运行:

gcc template_method.c -o template_method ./template_method

11. 访问者模式(Visitor Pattern)

通俗解释:表示一个作用于某对象结构中的各元素的操作,可以在不改变各元素类的前提下定义作用于这些元素的新操作。就像医生访问病人,对不同病人做不同检查。

生活例子:

  • 医生访问病人:对不同病人做不同检查
  • 税务审计:对不同公司做不同审计
  • 编译器:对不同语法节点做不同处理

适用场景:

  • 需要对对象结构中的元素执行不同操作
  • 需要在不改变元素类的情况下添加新操作

C语言实现:

#include<stdio.h>#include<stdlib.h>#include<string.h>// ========== 访问者接口 ==========typedefstructVisitor{void(*visitElementA)(structVisitor*self,void*element);// 访问元素Avoid(*visitElementB)(structVisitor*self,void*element);// 访问元素B}Visitor;// ========== 元素接口 ==========typedefstructElement{void(*accept)(void*self,Visitor*visitor);// 接受访问者charname[50];}Element;// ========== 具体元素A ==========typedefstruct{Element base;intvalueA;}ConcreteElementA;voidelementA_accept(void*self,Visitor*visitor){ConcreteElementA*elem=(ConcreteElementA*)self;printf("%s 接受访问\n",elem->base.name);visitor->visitElementA(visitor,elem);}ConcreteElementA*createElementA(constchar*name,intvalue){ConcreteElementA*elem=(ConcreteElementA*)malloc(sizeof(ConcreteElementA));strcpy(elem->base.name,name);elem->base.accept=elementA_accept;elem->valueA=value;returnelem;}// ========== 具体元素B ==========typedefstruct{Element base;charvalueB[50];}ConcreteElementB;voidelementB_accept(void*self,Visitor*visitor){ConcreteElementB*elem=(ConcreteElementB*)self;printf("%s 接受访问\n",elem->base.name);visitor->visitElementB(visitor,elem);}ConcreteElementB*createElementB(constchar*name,constchar*value){ConcreteElementB*elem=(ConcreteElementB*)malloc(sizeof(ConcreteElementB));strcpy(elem->base.name,name);elem->base.accept=elementB_accept;strcpy(elem->valueB,value);returnelem;}// ========== 具体访问者:操作1 ==========typedefstruct{Visitor base;}ConcreteVisitor1;voidvisitor1_visitElementA(Visitor*self,void*element){ConcreteElementA*elem=(ConcreteElementA*)element;printf("访问者1 访问元素A: %s,执行操作1,值: %d\n",elem->base.name,elem->valueA);}voidvisitor1_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;returnv;}// ========== 具体访问者:操作2 ==========typedefstruct{Visitor base;}ConcreteVisitor2;voidvisitor2_visitElementA(Visitor*self,void*element){ConcreteElementA*elem=(ConcreteElementA*)element;printf("访问者2 访问元素A: %s,执行操作2,值: %d\n",elem->base.name,elem->valueA);}voidvisitor2_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;returnv;}// ========== 对象结构 ==========typedefstruct{Element*elements[10];intcount;void(*add)(void*self,Element*element);void(*accept)(void*self,Visitor*visitor);}ObjectStructure;voidobjectStructure_add(void*self,Element*element){ObjectStructure*os=(ObjectStructure*)self;if(os->count<10){os->elements[os->count++]=element;}}voidobjectStructure_accept(void*self,Visitor*visitor){ObjectStructure*os=(ObjectStructure*)self;printf("\n=== 访问对象结构 ===\n");for(inti=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;returnos;}intmain(){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);return0;}

编译运行:

gcc visitor.c -o visitor ./visitor

总结:行为型模式

行为型模式帮助我们管理对象之间的通信和职责:

  • 责任链模式:将请求沿着处理者链传递
  • 命令模式:将请求封装成对象
  • 解释器模式:定义语言的文法并解释
  • 迭代器模式:顺序访问集合元素
  • 中介者模式:封装对象间的交互
  • 备忘录模式:保存和恢复对象状态
  • 观察者模式:一对多的依赖关系
  • 状态模式:根据状态改变行为
  • 策略模式:封装可互换的算法
  • 模板方法模式:定义算法骨架
  • 访问者模式:在不改变元素类的前提下定义新操作

每种模式都解决了不同的行为问题,让代码更灵活、更易维护。


完整总结:23种设计模式

创建型模式(5个)

  1. 单例模式
  2. 工厂方法模式
  3. 抽象工厂模式
  4. 建造者模式
  5. 原型模式

结构型模式(7个)

  1. 适配器模式
  2. 桥接模式
  3. 组合模式
  4. 装饰器模式
  5. 外观模式
  6. 享元模式
  7. 代理模式

行为型模式(11个)

  1. 责任链模式
  2. 命令模式
  3. 解释器模式
  4. 迭代器模式
  5. 中介者模式
  6. 备忘录模式
  7. 观察者模式
  8. 状态模式
  9. 策略模式
  10. 模板方法模式
  11. 访问者模式

所有模式都遵循7大设计原则,帮助我们写出更好的代码!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/27 11:15:11

nodeppt演讲者模式深度解析:打造专业级演讲体验

nodeppt演讲者模式深度解析&#xff1a;打造专业级演讲体验 【免费下载链接】nodeppt This is probably the best web presentation tool so far! 项目地址: https://gitcode.com/gh_mirrors/no/nodeppt 还在为演讲时手忙脚乱而烦恼吗&#xff1f;nodeppt的演讲者模式正…

作者头像 李华
网站建设 2025/12/23 0:13:44

终极指南:YouTube Music桌面版如何打造专属音乐空间

终极指南&#xff1a;YouTube Music桌面版如何打造专属音乐空间 【免费下载链接】ytmdesktop A Desktop App for YouTube Music 项目地址: https://gitcode.com/gh_mirrors/yt/ytmdesktop YouTube Music桌面版是一款功能强大的开源音乐播放器&#xff0c;为用户提供超越…

作者头像 李华
网站建设 2026/1/5 7:15:44

Wan2.2-T2V-A14B实现高质量运动过渡的算法机制揭秘

Wan2.2-T2V-A14B 实现高质量运动过渡的算法机制揭秘在短视频日均播放量突破百亿的时代&#xff0c;内容创作者早已不满足于“能出画面”——大家真正想要的是一段会呼吸的视频&#xff1a;人物动作自然流畅、场景转换丝滑无痕、风吹发梢都带着情绪。&#x1f3af; 可现实呢&…

作者头像 李华
网站建设 2026/1/8 22:45:44

VSCode连接量子设备全攻略(从零到专家级配置方案)

第一章&#xff1a;VSCode 的量子硬件连接配置 在现代量子计算开发中&#xff0c;Visual Studio Code&#xff08;VSCode&#xff09;已成为主流集成开发环境之一。通过扩展插件与底层API的结合&#xff0c;开发者可直接在VSCode中编写量子电路并连接真实量子硬件进行执行。 安…

作者头像 李华
网站建设 2026/1/8 12:34:09

VSCode遇上量子模拟:3个关键功能让你的编码速度翻倍

第一章&#xff1a;量子模拟器的 VSCode 扩展开发在现代量子计算研究中&#xff0c;开发者需要高效的工具链来编写、调试和模拟量子算法。Visual Studio Code 作为主流代码编辑器&#xff0c;其强大的扩展生态为集成量子模拟功能提供了理想平台。通过开发专用的 VSCode 扩展&am…

作者头像 李华
网站建设 2026/1/8 15:35:32

【加密PDF文档解析终极方案】:Dify平台深度集成技巧与实战秘籍

第一章&#xff1a;加密PDF文档解析的核心挑战在处理现代电子文档时&#xff0c;加密PDF文件的解析成为许多自动化系统与数据提取流程中的关键瓶颈。由于PDF格式本身支持多种加密机制&#xff08;如基于密码的40位或128位RC4加密、AES-256加密以及公钥加密&#xff09;&#xf…

作者头像 李华