大话设计模式C语言之桥接模式 桥接模式
桥接模式(Bridge Pattern)是结构型设计模式,主要通过将抽象部分与实现部分分离,使得二者可以独立变化分别使用。
案例代码 抽象部分
抽象部分(Abstraction)提供高层控制逻辑,依赖于完成底层实际工作的实现对象。
显示接口 display.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #ifndef DISPLAY_H #define DISPLAY_H #include "display_driver.h" typedef struct Display Display ;Display* display_create (DisplayDriverType type) ;void display_destroy (Display *display) ;void display_draw_circle (Display *display, int x,int y,int r) ;#endif
显示实现 display.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 #include <stdlib.h> #include "display.h" struct Display { DisplayDriver *driver; }; Display *display_create (DisplayDriverType type) { Display *d = malloc (sizeof (Display)); if (!d) return NULL ; d->driver = display_driver_create(type); if (!d->driver) { free (d); return NULL ; } return d; } void display_destroy (Display *display) { if (!display) return ; display_driver_destroy(display->driver); free (display); } void display_draw_circle (Display *display, int x, int y, int r) { if (!display) return ; display_driver_draw_circle(display->driver, x, y, r); }
精确抽象
精确抽象(Refined Abstraction)提供控制逻辑的变体。与其父类一样,它们通过通用实现接口与不同的实现进行交互。
精确抽象接口 circle_display.h 1 2 3 4 5 6 7 8 9 10 11 12 13 #ifndef CIRCLE_DISPLAY_H #define CIRCLE_DISPLAY_H #include "display.h" typedef struct CircleDisplay CircleDisplay ;CircleDisplay* circle_display_create (DisplayDriverType type, int x, int y, int radius) ;void circle_display_draw (CircleDisplay *circle) ;void circle_display_destroy (CircleDisplay *circle) ;#endif
精确抽象实现 circle_display.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include "circle_display.h" #include <stdlib.h> struct CircleDisplay { Display *display; int x; int y; int radius; }; CircleDisplay *circle_display_create (DisplayDriverType type, int x, int y, int r) { CircleDisplay *c = malloc (sizeof (CircleDisplay)); if (!c) return NULL ; c->display = display_create(type); if (!c->display) { free (c); return NULL ; } c->x = x; c->y = y; c->radius = r; return c; } void circle_display_draw (CircleDisplay *circle) { if (!circle) return ; display_draw_circle(circle->display, circle->x, circle->y, circle->radius); } void circle_display_destroy (CircleDisplay *circle) { if (!circle) return ; display_destroy(circle->display); free (circle); }
实现部分
实现部分(Implementation)为所有具体实现声明通用接口。抽象部分仅能通过在这里声明的方法与实现对象交互。抽象部分可以列出和实现部分一样的方法,但是抽象部分通常声明一些复杂行为,这些行为依赖于多种由实现部分声明的原语操作。
显示驱动接口 display_driver.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #ifndef DISPLAY_DRIVER_H #define DISPLAY_DRIVER_H typedef struct DisplayDriver DisplayDriver ;typedef enum { DISPLAY_DRIVER_SPI = 0 , DISPLAY_DRIVER_I2C } DisplayDriverType; DisplayDriver* display_driver_create (DisplayDriverType type) ;void display_driver_destroy (DisplayDriver *driver) ;void display_driver_draw_circle (DisplayDriver *driver, int x, int y, int radius) ;#endif
某种具体驱动 display_driver.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <stdio.h> #include <stdlib.h> #include "display_driver.h" struct DisplayDriver { void (*draw_circle)(int , int , int ); }; static void spi_draw_circle (int x, int y, int r) { printf ("[SPI] Draw Circle (%d,%d) r=%d\n" , x, y, r); } static void i2c_draw_circle (int x, int y, int r) { printf ("[I2C] Draw Circle (%d,%d) r=%d\n" , x, y, r); } DisplayDriver *display_driver_create (DisplayDriverType type) { DisplayDriver *driver = malloc (sizeof (DisplayDriver)); if (!driver) return NULL ; switch (type) { case DISPLAY_DRIVER_SPI: driver->draw_circle = spi_draw_circle; break ; case DISPLAY_DRIVER_I2C: driver->draw_circle = i2c_draw_circle; break ; default : free (driver); return NULL ; } return driver; } void display_driver_destroy (DisplayDriver *driver) { if (driver) free (driver); } void display_driver_draw_circle (DisplayDriver *driver, int x, int y, int radius) { if (driver && driver->draw_circle) driver->draw_circle(x, y, radius); }
测试客户端代码 main.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include "circle_display.h" int main (void ) { CircleDisplay *c1 = circle_display_create(DISPLAY_DRIVER_SPI, 10 , 20 , 5 ); CircleDisplay *c2 = circle_display_create(DISPLAY_DRIVER_I2C, 30 , 40 , 8 ); circle_display_draw(c1); circle_display_draw(c2); circle_display_destroy(c1); circle_display_destroy(c2); while (1 ); return 0 ; }
总结 桥接模式可以创建与平台无关的程序,客户端代码仅与高层抽象部分交互,而无需了解底层实现。即使新增抽象部分和实现部分它们之间不会相互影响。抽象部分专注于处理高层逻辑,实现部分处理平台细节。 如果你需要在运行时切换不同实现方法,可使用桥接模式。当然并不是说一定要实现这一点,桥接模式可替换抽象部分中的实现对象,具体操作就和给成员变量赋新值一样简单。最后一点是很多人混淆桥接模式和策略模式的主要原因。设计模式并不仅是一种对类进行组织的方式,它还能用于沟通意图和解决问题。