1.简介
在软件工程中,设计模式是一种被广泛采用的解决特定问题的方法。其中,“外观模式”(Facade Pattern)是一种结构型设计模式,它的主要目的是提供一个统一的接口来访问一系列复杂的子系统。这使得客户端与子系统的内部细节解耦,并简化了客户端的使用。
外观模式通过提供一个高层次的接口,让子系统更容易使用。它不改变子系统的功能,而是为它们提供了一个简单明了的界面。这种模式可以用于以下情况:
- 当一个系统过于复杂,需要一个简化的接口。
- 当用户只需要使用一个子系统的一个小部分功能。
- 当你需要降低子系统与其他组件之间的耦合度。
2.通俗讲解
假设我们有一个简单的音频播放器系统,它由多个模块组成:音量控制、播放/暂停、上一首/下一首等功能。我们可以使用外观模式来简化这个系统的接口。
3.实战
3.1.代码
#include <stdio.h>
#include <string.h>
// Volume Control Module
typedef struct {
int volume;
} VolumeControl;
VolumeControl volumeControl = {50}; // Default volume is 50
void setVolume(VolumeControl *vc, int vol) {
vc->volume = vol;
}
int getVolume(VolumeControl *vc) {
return vc->volume;
}
// Media Player Module
typedef struct {
char currentSong[100];
} MediaPlayer;
MediaPlayer mediaPlayer = {"No Song"};
void playSong(MediaPlayer *mp, const char *song) {
strcpy(mp->currentSong, song);
printf("Playing: %s\n", mp->currentSong);
}
void pauseSong(MediaPlayer *mp) {
printf("Paused: %s\n", mp->currentSong);
}
void nextSong(MediaPlayer *mp, const char *song) {
strcpy(mp->currentSong, song);
printf("Next Song: %s\n", mp->currentSong);
}
void prevSong(MediaPlayer *mp, const char *song) {
strcpy(mp->currentSong, song);
printf("Previous Song: %s\n", mp->currentSong);
}
// Audio Player Facade
typedef struct {
VolumeControl *volumeCtrl;
MediaPlayer *player;
} AudioPlayerFacade;
AudioPlayerFacade audioPlayerFacade = {&volumeControl, &mediaPlayer};
void playAudio(AudioPlayerFacade *facade, const char *song, int volume) {
playSong(facade->player, song);
setVolume(facade->volumeCtrl, volume);
}
void pauseAudio(AudioPlayerFacade *facade) {
pauseSong(facade->player);
}
void nextAudio(AudioPlayerFacade *facade, const char *song) {
nextSong(facade->player, song);
}
void prevAudio(AudioPlayerFacade *facade, const char *song) {
prevSong(facade->player, song);
}
void setVolumeAudio(AudioPlayerFacade *facade, int volume) {
setVolume(facade->volumeCtrl, volume);
}
void getVolumeAudio(AudioPlayerFacade *facade) {
printf("Current Volume: %d\n", getVolume(facade->volumeCtrl));
}
// Main function
int main() {
AudioPlayerFacade *facade = &audioPlayerFacade;
playAudio(facade, "Bohemian Rhapsody", 75);
pauseAudio(facade);
nextAudio(facade, "Stairway to Heaven");
prevAudio(facade, "Bohemian Rhapsody");
setVolumeAudio(facade, 85);
getVolumeAudio(facade);
return 0;
}
3.2.代码解析
- 在 main 函数中,创建了一个指向 audioPlayerFacade 的指针 facade。
- 使用 playAudio 函数播放歌曲 “Bohemian Rhapsody” 并将音量设置为 75。
- 使用 pauseAudio 函数暂停当前播放的歌曲。
- 使用 nextAudio 函数播放下一首歌曲 “Stairway to Heaven”。
- 使用 prevAudio 函数返回播放 “Bohemian Rhapsody”。
- 使用 setVolumeAudio 函数将音量设置为 85。
- 使用 getVolumeAudio 函数打印当前音量。
通过上面的例子,我们看到外观模式如何简化了客户端对子系统的使用。客户端只需知道AudioPlayerFacade提供的接口即可,而不需要了解每个模块的具体实现。这种方式不仅降低了系统的复杂性,还提高了可维护性和扩展性。当系统需要添加新的功能或修改现有功能时,外观类可以保持不变,从而不影响到客户端代码。
3.3.代码运行
Playing: Bohemian Rhapsody
Paused: Bohemian Rhapsody
Next Song: Stairway to Heaven
Previous Song: Bohemian Rhapsody
Current Volume: 85
3.4.结果分析
从输出结果可以看出,程序首先播放了一首歌曲“Bohemian Rhapsody”,并将音量设置为75。接着,它暂停了正在播放的歌曲,然后跳转到下一首歌曲“Stairway to Heaven”。之后,又返回到上一首歌曲“Bohemian Rhapsody”。最后,它将音量调整到了85,并输出了当前的音量值。
通过使用外观模式,我们把原本需要调用多个不同模块的操作封装到了一个简洁的接口中。这样做的好处是,客户端代码只需要关心外观类提供的接口,而无需了解底层模块的实现细节。这种方式不仅简化了客户端的使用,也提高了系统的可维护性和可扩展性。
4.总结
- 优点:
- 简化了客户端与子系统的交互。
- 提高了系统的可维护性和可扩展性。
- 降低了客户端与子系统之间不必要的依赖。
- 缺点:
- 如果外观类变得过于庞大,可能会引入新的复杂性。
- 可能增加代码量,特别是在子系统本身就很简单的场景下。
- 适用场景:
- 当一个系统过于复杂,需要一个简化的接口。
- 当用户只需要使用一个子系统的一部分功能。
- 当需要降低子系统与其他组件之间的耦合度。