18.设计模式-桥接模式

桥接模式(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图

总结

  • 合成/聚合复用原则的好处:优先使用对象的合成/聚合将有助于你保持每个类被封装,并被集中在单个任务上。这样类和类继承层次会保持较小规模,并且不太可能增长为不可控制的庞然大物。
相关推荐
杨充19 小时前
10.可测试性实战设计
设计模式·开源·代码规范
杨充19 小时前
9.重构十二式的实战
设计模式·开源·代码规范
杨充19 小时前
6.设计原则的全景图
设计模式·开源·全栈
杨充19 小时前
2.面向对象的特性
设计模式
杨充19 小时前
7.SOLID原则案例汇
设计模式·开源·全栈
杨充19 小时前
8.反模式与坏味道
设计模式·开源·代码规范
杨充19 小时前
3.接口vs抽象类比较
设计模式
咖啡八杯1 天前
文法、BNF与AST
java·设计模式·解释器模式·ast·文法
咖啡八杯1 天前
GoF设计模式——解释器模式
java·后端·spring·设计模式