桥接模式(Bridge Pattern)的核心是将抽象部分与实现部分分离,使两者可以独立变化 ,避免抽象与实现的紧耦合(如通过继承导致的类爆炸)。在C语言中,可以通过两个独立的结构体层次(抽象层和实现层)+ 指针关联实现:抽象层包含实现层的指针,通过指针调用具体实现,实现抽象与实现的解耦。
C语言实现桥接模式的思路
- 实现接口(Implementor):定义实现部分的统一接口(函数指针结构体),是具体实现的抽象。
- 具体实现(Concrete Implementor) :实现
Implementor接口,提供具体的功能实现(如不同平台的操作)。 - 抽象类(Abstraction) :定义抽象部分的接口,内部包含
Implementor指针,通过该指针调用实现层的功能。 - 扩展抽象类(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
核心思想总结
- 分离抽象与实现 :抽象层(
Shape、Circle)与实现层(DrawAPI、WindowsDraw)通过指针(draw_api)桥接,两者可独立扩展(新增形状无需修改平台代码,新增平台无需修改形状代码)。 - 减少耦合 :避免了"形状×平台"的多重继承(如
WindowsCircle、LinuxCircle等冗余类),通过组合(抽象包含实现指针)实现灵活关联。 - 扩展性 :
- 新增形状(如三角形):只需实现新的
Shape扩展类,复用现有DrawAPI。 - 新增平台(如macOS):只需实现新的
DrawAPI,现有形状可直接使用。
- 新增形状(如三角形):只需实现新的
C语言通过结构体指针将抽象层与实现层关联,完美体现了桥接模式"分离抽象与实现"的核心,适合处理多维度变化的场景(如跨平台开发、多协议支持等)。