外观模式(Facade Pattern)的核心是为复杂系统提供一个简化的统一接口 ,隐藏系统内部的复杂性,使客户端能更轻松地使用系统。在C语言中,可以通过封装多个子模块的接口,提供一个高层接口函数实现:客户端只需调用外观接口,无需直接操作底层子模块。
C语言实现外观模式的思路
- 子系统(Subsystem):由多个相互关联的模块组成,每个模块有自己的接口(如函数)。
- 外观(Facade):封装子系统的接口,提供一个简化的高层接口,协调子系统的调用流程。
- 客户端(Client):仅与外观交互,无需了解子系统的内部细节。
示例:智能家居控制系统(简化多个设备的操作)
假设一个智能家居系统包含灯光、空调、窗帘等子系统,每个子系统有复杂的控制逻辑(如开灯、调温、关窗帘)。外观模式可提供一个"一键离家"接口,自动关闭所有设备,简化操作。
步骤1:定义子系统(各设备模块)
子系统包含多个独立的设备控制逻辑,各自有不同的接口。
c
#include <stdio.h>
// 子系统1:灯光控制
typedef struct {
int is_on; // 灯光状态:0-关,1-开
} Light;
// 初始化灯光
void light_init(Light* light) {
light->is_on = 0;
printf("灯光初始化完成(关闭状态)\n");
}
// 打开灯光
void light_turn_on(Light* light) {
light->is_on = 1;
printf("灯光已打开\n");
}
// 关闭灯光
void light_turn_off(Light* light) {
light->is_on = 0;
printf("灯光已关闭\n");
}
// 子系统2:空调控制
typedef struct {
int is_on; // 空调状态:0-关,1-开
int temp; // 温度(℃)
} AirConditioner;
// 初始化空调
void ac_init(AirConditioner* ac) {
ac->is_on = 0;
ac->temp = 26; // 默认温度
printf("空调初始化完成(关闭状态,默认26℃)\n");
}
// 打开空调并设置温度
void ac_turn_on(AirConditioner* ac, int temp) {
ac->is_on = 1;
ac->temp = temp;
printf("空调已打开,温度设置为%d℃\n", temp);
}
// 关闭空调
void ac_turn_off(AirConditioner* ac) {
ac->is_on = 0;
printf("空调已关闭\n");
}
// 子系统3:窗帘控制
typedef struct {
int is_closed; // 窗帘状态:0-开,1-关
} Curtain;
// 初始化窗帘
void curtain_init(Curtain* curtain) {
curtain->is_closed = 0;
printf("窗帘初始化完成(打开状态)\n");
}
// 关闭窗帘
void curtain_close(Curtain* curtain) {
curtain->is_closed = 1;
printf("窗帘已关闭\n");
}
// 打开窗帘
void curtain_open(Curtain* curtain) {
curtain->is_closed = 0;
printf("窗帘已打开\n");
}
步骤2:实现外观(统一控制接口)
外观封装所有子系统,提供简化的接口(如"离家模式""回家模式"),内部协调子系统的调用顺序。
c
// 外观:智能家居控制器
typedef struct {
Light light; // 包含灯光子系统
AirConditioner ac; // 包含空调子系统
Curtain curtain; // 包含窗帘子系统
} SmartHomeFacade;
// 初始化外观(内部初始化所有子系统)
void smart_home_init(SmartHomeFacade* facade) {
printf("\n=== 初始化智能家居系统 ===\n");
light_init(&facade->light);
ac_init(&facade->ac);
curtain_init(&facade->curtain);
}
// 外观接口1:离家模式(关闭所有设备)
void smart_home_leave_mode(SmartHomeFacade* facade) {
printf("\n=== 执行离家模式 ===\n");
light_turn_off(&facade->light); // 关闭灯光
ac_turn_off(&facade->ac); // 关闭空调
curtain_close(&facade->curtain); // 关闭窗帘
}
// 外观接口2:回家模式(打开常用设备)
void smart_home_arrive_mode(SmartHomeFacade* facade) {
printf("\n=== 执行回家模式 ===\n");
light_turn_on(&facade->light); // 打开灯光
ac_turn_on(&facade->ac, 24); // 打开空调(24℃)
curtain_open(&facade->curtain); // 打开窗帘
}
步骤3:使用外观模式
客户端只需调用外观提供的简化接口,无需直接操作子系统。
c
int main() {
// 创建外观对象
SmartHomeFacade home;
// 初始化系统(通过外观)
smart_home_init(&home);
// 回家:调用外观的回家模式
smart_home_arrive_mode(&home);
// 离家:调用外观的离家模式
smart_home_leave_mode(&home);
return 0;
}
输出结果
=== 初始化智能家居系统 ===
灯光初始化完成(关闭状态)
空调初始化完成(关闭状态,默认26℃)
窗帘初始化完成(打开状态)
=== 执行回家模式 ===
灯光已打开
空调已打开,温度设置为24℃
窗帘已打开
=== 执行离家模式 ===
灯光已关闭
空调已关闭
窗帘已关闭
核心思想总结
- 简化接口 :外观将多个子系统的复杂接口(如
light_turn_on
、ac_turn_on
)封装为少数几个高层接口(如smart_home_arrive_mode
),降低客户端使用难度。 - 隐藏细节 :客户端无需了解子系统的内部实现(如灯光的
is_on
状态、空调的温度控制逻辑),只需通过外观交互。 - 解耦客户端与子系统 :子系统的修改(如新增设备、修改控制逻辑)只需调整外观,无需修改客户端代码,符合迪米特法则(最少知识原则)。
C语言通过结构体包含子系统对象,结合函数封装子系统调用流程,实现了外观模式的核心。这种模式适合整合多个复杂模块(如硬件驱动、第三方库、子系统),为上层提供简洁接口。