用C语言实现桥接模式

桥接模式(Bridge Pattern)的核心是将抽象部分与实现部分分离,使两者可以独立变化 ,避免抽象与实现的紧耦合(如通过继承导致的类爆炸)。在C语言中,可以通过两个独立的结构体层次(抽象层和实现层)+ 指针关联实现:抽象层包含实现层的指针,通过指针调用具体实现,实现抽象与实现的解耦。

C语言实现桥接模式的思路

  1. 实现接口(Implementor):定义实现部分的统一接口(函数指针结构体),是具体实现的抽象。
  2. 具体实现(Concrete Implementor) :实现Implementor接口,提供具体的功能实现(如不同平台的操作)。
  3. 抽象类(Abstraction) :定义抽象部分的接口,内部包含Implementor指针,通过该指针调用实现层的功能。
  4. 扩展抽象类(Refined Abstraction) :继承Abstraction,扩展抽象接口的功能,但仍通过Implementor指针调用实现。

示例:跨平台图形绘制(抽象形状与平台绘制分离)

假设需要绘制圆形和矩形,且要支持Windows和Linux两种平台的绘制API。桥接模式可将"形状(抽象)"与"平台绘制(实现)"分离,两者可独立扩展(新增形状或平台无需修改对方)。

步骤1:定义实现接口(平台绘制接口)
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 实现接口:平台绘制操作的抽象(定义绘制基本图形的接口)
typedef struct DrawAPI {
    // 绘制圆形(x,y:中心坐标,radius:半径)
    void (*draw_circle)(struct DrawAPI* self, int x, int y, int radius);
    // 绘制矩形(x,y:左上角坐标,width,height:宽高)
    void (*draw_rectangle)(struct DrawAPI* self, int x, int y, int width, int height);
} DrawAPI;
步骤2:实现具体的平台绘制(Windows和Linux)

具体实现DrawAPI接口,提供不同平台的绘制逻辑。

2.1 Windows平台绘制
c 复制代码
// 具体实现1:Windows平台绘制
typedef struct {
    DrawAPI draw_api; // 实现DrawAPI接口
} WindowsDraw;

// Windows绘制圆形
static void windows_draw_circle(DrawAPI* self, int x, int y, int radius) {
    printf("Windows绘制圆形:中心(%d,%d),半径%d\n", x, y, radius);
}

// Windows绘制矩形
static void windows_draw_rectangle(DrawAPI* self, int x, int y, int width, int height) {
    printf("Windows绘制矩形:左上角(%d,%d),宽%d,高%d\n", x, y, width, height);
}

// 初始化Windows绘制实现
DrawAPI* windows_draw_create() {
    WindowsDraw* win_draw = (WindowsDraw*)malloc(sizeof(WindowsDraw));
    if (!win_draw) return NULL;
    // 绑定接口方法
    win_draw->draw_api.draw_circle = windows_draw_circle;
    win_draw->draw_api.draw_rectangle = windows_draw_rectangle;
    return (DrawAPI*)win_draw;
}
2.2 Linux平台绘制
c 复制代码
// 具体实现2:Linux平台绘制
typedef struct {
    DrawAPI draw_api; // 实现DrawAPI接口
} LinuxDraw;

// Linux绘制圆形
static void linux_draw_circle(DrawAPI* self, int x, int y, int radius) {
    printf("Linux绘制圆形:中心(%d,%d),半径%d\n", x, y, radius);
}

// Linux绘制矩形
static void linux_draw_rectangle(DrawAPI* self, int x, int y, int width, int height) {
    printf("Linux绘制矩形:左上角(%d,%d),宽%d,高%d\n", x, y, width, height);
}

// 初始化Linux绘制实现
DrawAPI* linux_draw_create() {
    LinuxDraw* linux_draw = (LinuxDraw*)malloc(sizeof(LinuxDraw));
    if (!linux_draw) return NULL;
    // 绑定接口方法
    linux_draw->draw_api.draw_circle = linux_draw_circle;
    linux_draw->draw_api.draw_rectangle = linux_draw_rectangle;
    return (DrawAPI*)linux_draw;
}
步骤3:定义抽象层(形状接口)

抽象层包含DrawAPI指针,通过该指针调用具体绘制实现,自身只定义形状的抽象行为(如draw)。

c 复制代码
// 抽象类:形状(包含实现层指针)
typedef struct Shape {
    DrawAPI* draw_api; // 指向实现层(桥接的核心:抽象与实现通过指针关联)
    
    // 抽象方法:绘制形状
    void (*draw)(struct Shape* self);
    // 销毁形状
    void (*destroy)(struct Shape* self);
} Shape;
步骤4:实现扩展抽象类(具体形状:圆形和矩形)

扩展抽象类继承Shape,实现draw方法,通过draw_api调用具体平台的绘制功能。

4.1 圆形(扩展抽象类)
c 复制代码
// 扩展抽象类1:圆形
typedef struct {
    Shape shape; // 继承Shape抽象类
    int x, y;    // 中心坐标
    int radius;  // 半径
} Circle;

// 圆形的绘制:调用实现层的draw_circle
static void circle_draw(Shape* self) {
    Circle* circle = (Circle*)self;
    // 通过桥接的draw_api调用具体绘制(不关心是Windows还是Linux)
    self->draw_api->draw_circle(self->draw_api, circle->x, circle->y, circle->radius);
}

// 圆形的销毁
static void circle_destroy(Shape* self) {
    free(self);
}

// 创建圆形(关联实现层接口)
Shape* circle_create(DrawAPI* draw_api, int x, int y, int radius) {
    if (!draw_api) return NULL;
    Circle* circle = (Circle*)malloc(sizeof(Circle));
    if (!circle) return NULL;
    
    // 初始化抽象类部分
    circle->shape.draw_api = draw_api; // 绑定实现层
    circle->shape.draw = circle_draw;
    circle->shape.destroy = circle_destroy;
    
    // 初始化圆形特有属性
    circle->x = x;
    circle->y = y;
    circle->radius = radius;
    
    return (Shape*)circle;
}
4.2 矩形(扩展抽象类)
c 复制代码
// 扩展抽象类2:矩形
typedef struct {
    Shape shape;   // 继承Shape抽象类
    int x, y;      // 左上角坐标
    int width;     // 宽
    int height;    // 高
} Rectangle;

// 矩形的绘制:调用实现层的draw_rectangle
static void rectangle_draw(Shape* self) {
    Rectangle* rect = (Rectangle*)self;
    self->draw_api->draw_rectangle(self->draw_api, rect->x, rect->y, rect->width, rect->height);
}

// 矩形的销毁
static void rectangle_destroy(Shape* self) {
    free(self);
}

// 创建矩形(关联实现层接口)
Shape* rectangle_create(DrawAPI* draw_api, int x, int y, int width, int height) {
    if (!draw_api) return NULL;
    Rectangle* rect = (Rectangle*)malloc(sizeof(Rectangle));
    if (!rect) return NULL;
    
    // 初始化抽象类部分
    rect->shape.draw_api = draw_api; // 绑定实现层
    rect->shape.draw = rectangle_draw;
    rect->shape.destroy = rectangle_destroy;
    
    // 初始化矩形特有属性
    rect->x = x;
    rect->y = y;
    rect->width = width;
    rect->height = height;
    
    return (Shape*)rect;
}
步骤5:使用桥接模式

客户端可自由组合抽象层(形状)和实现层(平台绘制),两者独立变化。

c 复制代码
int main() {
    // 1. 创建实现层:Windows和Linux绘制接口
    DrawAPI* windows_draw = windows_draw_create();
    DrawAPI* linux_draw = linux_draw_create();
    
    // 2. 组合1:Windows平台绘制圆形和矩形
    printf("=== Windows平台图形 ===\n");
    Shape* win_circle = circle_create(windows_draw, 10, 20, 5);
    Shape* win_rect = rectangle_create(windows_draw, 30, 40, 20, 15);
    win_circle->draw(win_circle);
    win_rect->draw(win_rect);
    
    // 3. 组合2:Linux平台绘制圆形和矩形
    printf("\n=== Linux平台图形 ===\n");
    Shape* linux_circle = circle_create(linux_draw, 10, 20, 5);
    Shape* linux_rect = rectangle_create(linux_draw, 30, 40, 20, 15);
    linux_circle->draw(linux_circle);
    linux_rect->draw(linux_rect);
    
    // 4. 清理资源
    win_circle->destroy(win_circle);
    win_rect->destroy(win_rect);
    linux_circle->destroy(linux_circle);
    linux_rect->destroy(linux_rect);
    free(windows_draw);
    free(linux_draw);
    
    return 0;
}

输出结果

复制代码
=== Windows平台图形 ===
Windows绘制圆形:中心(10,20),半径5
Windows绘制矩形:左上角(30,40),宽20,高15

=== Linux平台图形 ===
Linux绘制圆形:中心(10,20),半径5
Linux绘制矩形:左上角(30,40),宽20,高15

核心思想总结

  1. 分离抽象与实现 :抽象层(ShapeCircle)与实现层(DrawAPIWindowsDraw)通过指针(draw_api)桥接,两者可独立扩展(新增形状无需修改平台代码,新增平台无需修改形状代码)。
  2. 减少耦合 :避免了"形状×平台"的多重继承(如WindowsCircleLinuxCircle等冗余类),通过组合(抽象包含实现指针)实现灵活关联。
  3. 扩展性
    • 新增形状(如三角形):只需实现新的Shape扩展类,复用现有DrawAPI
    • 新增平台(如macOS):只需实现新的DrawAPI,现有形状可直接使用。

C语言通过结构体指针将抽象层与实现层关联,完美体现了桥接模式"分离抽象与实现"的核心,适合处理多维度变化的场景(如跨平台开发、多协议支持等)。

相关推荐
散峰而望2 小时前
C/C++输入输出初级(一) (算法竞赛)
c语言·开发语言·c++·算法·github
是苏浙5 小时前
零基础入门C语言之C语言实现数据结构之单链表经典算法
c语言·开发语言·数据结构·算法
71-37 小时前
C语言练习题——判断水仙花数(0-100000)
c语言·笔记·学习
jzhwolp8 小时前
从基本链表到侵入式链表,体会内核设计思路
c语言·后端·设计模式
biter down9 小时前
c语言18:结构体位段联合体
c语言·开发语言
程序员buddha10 小时前
C语言操作符详解
java·c语言·算法
云知谷12 小时前
【经典书籍】《代码整洁之道》第六章“对象与数据结构”精华讲解
c语言·开发语言·c++·软件工程·团队开发
树在风中摇曳13 小时前
C语言 | 文件操作详解与实战示例
c语言·开发语言
雨落在了我的手上14 小时前
C语言入门(十六):指针(2)
c语言
say_fall14 小时前
C语言编程实战:每日刷题 - day 1
c语言·开发语言·学习