Dependency inversion principle(DIP依赖倒置原则)

一.what is dependency inversion principle( DIP依赖倒置原则 )

DIP 是指高层模块不应该依赖于低层模块,二者都应该依赖于抽象;抽象不应该依赖于细节,细节应该依赖于抽象。

二.DIP的设计准则

  • 高层模块不应该依赖于低层模块:高层模块(如业务逻辑)不应该直接依赖于低层模块(如芯片SDK)。相反,它们应该依赖于抽象(接口或抽象类)。
  • 抽象不应该依赖具体实现
  • 细节应该依赖于抽象:具体实现(如类或函数)应该依赖于抽象(接口或抽象类),而不是直接依赖于其他具体实现。

三.举例

3.1 设备开关反例

不符合 DIP 的写法(高层switch.c直接依赖低层具体实现light.h),Switch 模块硬编码依赖了具体的 Light 实现,换成风扇、蜂鸣器就得改 Switch 代码。

复制代码
// light.h / light.c
void Light_On()  { /* 点亮 GPIO */ }
void Light_Off() { /* 熄灭 GPIO */ }

// switch.c (高层模块)
#include "light.h"

void Switch_Press() {
    static int state = 0;
    state = !state;
    if (state) Light_On();
    else       Light_Off();
}

3.2 设备开关符合 DIP 的写法

高层(switch.c、switch.h)依赖抽象层(device.h),低层的具体实现(led.c、buzzer.c)也依赖抽象层(device.h)。

device.h(抽象层)
点击查看代码

复制代码
// device.h   ← 抽象层(接口定义)
#ifndef DEVICE_H
#define DEVICE_H

typedef struct {
    void (*turn_on)(void);   // 函数指针
    void (*turn_off)(void);
} DeviceOperations;

void Switch_Press(const DeviceOperations* dev);

#endif

switch.c(高层模块只依赖抽象)
点击查看代码

复制代码
// switch.c
#include "device.h"
#include <stdio.h>

static int state = 0;

void Switch_Press(const DeviceOperations* dev) {
    state = !state; /*只做演示,实际每个设备都需维护一个状态*/
    if (state) {
        printf("Switch: ON → ");
        dev->turn_on();
    } else {
        printf("Switch: OFF → ");
        dev->turn_off();
    }
}

led.c(低层模块也依赖抽象)
点击查看代码

复制代码
// led.c   ← 具体低层实现1
#include <stdio.h>
#include "device.h"

static void Led_On(void)  { printf("LED 点亮\n"); }
static void Led_Off(void) { printf("LED 熄灭\n"); }

const DeviceOperations LedDevice = {
    .turn_on  = Led_On,
    .turn_off = Led_Off
};

buzzer.c
点击查看代码

复制代码
// buzzer.c   ← 具体低层实现2(可替换)
#include <stdio.h>
#include "device.h"

static void Buzzer_On(void)  { printf("蜂鸣器鸣叫\n"); }
static void Buzzer_Off(void) { printf("蜂鸣器静音\n"); }

const DeviceOperations BuzzerDevice = {
    .turn_on  = Buzzer_On,
    .turn_off = Buzzer_Off
};

main.c(测试代码)
点击查看代码

复制代码
// main.c
#include "device.h"
#include "switch.c"   // 为了演示,实际项目中用 .h + .c 分离

extern const DeviceOperations LedDevice;
extern const DeviceOperations BuzzerDevice;

int main(void) {
    printf("使用 LED 设备:\n");
    Switch_Press(&LedDevice);
    Switch_Press(&LedDevice);

    printf("\n使用 蜂鸣器 设备:\n");
    Switch_Press(&BuzzerDevice);
    Switch_Press(&BuzzerDevice);

    return 0;
}