桥接模式(Bridge):将抽象部分与它的实现部分分离,使它们都可以独立地变化
合成/聚合复用原则(CARP),尽量使用合成/聚合,尽量不要使用类继承。

由于实现的方式有多种,桥接模式的核心意图就是把这些实现独立出来,让它们各自地变化。这就使得每种实现的变化不会影响其他实现,从而达到应对变化的目的。
代码
本例中就是让'手机'既可以按照品牌来分类,也可以按照功能来分类。当品牌需要实现功能时,通过调用功能类实现。
业务类
c
#include <stdio.h>
#include <stdlib.h>
typedef struct HandsetSoft {
void (*run)();
} HandsetSoft;
typedef struct HandsetGame {
HandsetSoft base;
} HandsetGame;
void HandsetGameRun() {
printf("运行手机游戏\n");
}
HandsetSoft *InitHandsetGame() {
HandsetGame *obj = (HandsetGame *)malloc(sizeof(HandsetGame));
obj->base.run = HandsetGameRun;
return (HandsetSoft *)obj;
}
typedef struct HandsetAddressList {
HandsetSoft base;
} HandsetAddressList;
void HandsetAddressListRun() {
printf("运行手机通讯录\n");
}
HandsetSoft *InitHandsetAddressList() {
HandsetAddressList *obj = (HandsetAddressList *)malloc(sizeof(HandsetAddressList));
obj->base.run = HandsetAddressListRun;
return (HandsetSoft *)obj;
}
typedef struct HandsetBrand {
HandsetSoft *soft;
void (*run)(struct HandsetBrand *);
void (*setSoft)(struct HandsetBrand *, struct HandsetSoft *);
} HandsetBrand;
typedef struct HandsetBrandN {
HandsetBrand base;
} HandsetBrandN;
void HandsetBrandNSetSoft(HandsetBrand *obj, HandsetSoft *soft) {
obj->soft = soft;
}
void HandsetBrandNRun(HandsetBrand *obj) {
printf("手机品牌N ");
obj->soft->run();
}
HandsetBrand *InitHandsetBrandN() {
HandsetBrandN *obj = (HandsetBrandN *)malloc(sizeof(HandsetBrandN));
obj->base.setSoft = HandsetBrandNSetSoft;
obj->base.run = HandsetBrandNRun;
return (HandsetBrand *)obj;
}
typedef struct HandsetBrandM {
HandsetBrand base;
} HandsetBrandM;
void HandsetBrandMSetSoft(HandsetBrand *obj, HandsetSoft *soft) {
if(obj->soft != NULL) {
free(obj->soft);
}
obj->soft = soft;
}
void HandsetBrandMRun(HandsetBrand *obj) {
printf("手机品牌M ");
obj->soft->run();
}
HandsetBrand *InitHandsetBrandM() {
HandsetBrandM *obj = (HandsetBrandM *)malloc(sizeof(HandsetBrandM));
obj->base.setSoft = HandsetBrandMSetSoft;
obj->base.run = HandsetBrandMRun;
obj->base.soft = NULL;
return (HandsetBrand *)obj;
}
客户端
c
int main() {
HandsetBrand *ab = InitHandsetBrandN();
ab->setSoft(ab, InitHandsetGame());
ab->run(ab);
ab->setSoft(ab,InitHandsetAddressList());
ab->run(ab);
free(ab->soft);
free(ab);
ab = InitHandsetBrandM();
ab->setSoft(ab, InitHandsetGame());
ab->run(ab);
ab->setSoft(ab, InitHandsetAddressList());
ab->run(ab);
free(ab->soft);
free(ab);
return 0;
}
UML图

总结
- 合成/聚合复用原则的好处:优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。