外观模式 (Facade)
外观模式 是一种结构型设计模式,为子系统中的一组接口提供一个一致的界面。外观模式定义了一个更高层次的接口,使得子系统更容易使用。
意图
- 简化复杂子系统的接口。
- 为客户端提供一个统一的入口,屏蔽子系统的内部细节。
使用场景
-
隐藏复杂性:
- 系统的子系统结构复杂,客户端需要简化与子系统的交互。
-
提供统一接口:
- 多个子系统有多个接口,外观模式统一了接口,简化了调用。
-
降低耦合性:
- 客户端与子系统直接耦合,通过外观模式降低依赖。
参与者角色
-
外观 (Facade)
- 为客户端提供一个简单的接口,隐藏子系统的复杂性。
-
子系统 (Subsystem)
- 子系统的具体实现,包含实际业务逻辑。子系统可能被多个外观类调用。
-
客户端 (Client)
- 通过外观类与子系统交互,无需直接访问子系统。
示例代码
以下代码展示了如何使用外观模式简化对一个家庭影院子系统的操作。
#include <iostream>
#include <string>
// 子系统类:DVD播放器
class DVDPlayer {
public:
void on() {
std::cout << "DVD Player is ON." << std::endl;
}
void off() {
std::cout << "DVD Player is OFF." << std::endl;
}
void play(const std::string& movie) {
std::cout << "Playing movie: " << movie << std::endl;
}
};
// 子系统类:音响
class SoundSystem {
public:
void on() {
std::cout << "Sound System is ON." << std::endl;
}
void off() {
std::cout << "Sound System is OFF." << std::endl;
}
void setVolume(int level) {
std::cout << "Setting volume to " << level << std::endl;
}
};
// 子系统类:灯光
class Lighting {
public:
void dim() {
std::cout << "Lights are dimmed." << std::endl;
}
void on() {
std::cout << "Lights are ON." << std::endl;
}
};
// 外观类:家庭影院外观
class HomeTheaterFacade {
private:
DVDPlayer* dvdPlayer;
SoundSystem* soundSystem;
Lighting* lighting;
public:
HomeTheaterFacade(DVDPlayer* dvd, SoundSystem* sound, Lighting* light)
: dvdPlayer(dvd), soundSystem(sound), lighting(light) {}
void watchMovie(const std::string& movie) {
std::cout << "Get ready to watch a movie..." << std::endl;
lighting->dim();
soundSystem->on();
soundSystem->setVolume(5);
dvdPlayer->on();
dvdPlayer->play(movie);
}
void endMovie() {
std::cout << "Shutting down the home theater..." << std::endl;
dvdPlayer->off();
soundSystem->off();
lighting->on();
}
};
// 客户端代码
int main() {
// 创建子系统对象
DVDPlayer dvdPlayer;
SoundSystem soundSystem;
Lighting lighting;
// 创建外观对象
HomeTheaterFacade homeTheater(&dvdPlayer, &soundSystem, &lighting);
// 使用外观模式
homeTheater.watchMovie("Inception");
homeTheater.endMovie();
return 0;
}
代码解析
1. 子系统类
DVDPlayer
、SoundSystem
和Lighting
是子系统的具体实现,提供了功能性接口。- 每个子系统类都独立完成自己的职责。
2. 外观类
HomeTheaterFacade
是外观类,封装了多个子系统的操作。- 提供了简化的接口
watchMovie
和endMovie
,让客户端能够轻松调用复杂子系统。
3. 客户端
- 客户端直接调用外观类的方法,而不需要关心子系统的内部逻辑。
优缺点
优点
-
简化接口:
- 客户端通过外观类与子系统交互,降低了使用难度。
-
松散耦合:
- 客户端与子系统之间的耦合性降低,通过外观类隔离依赖。
-
更好的划分子系统:
- 外观类将子系统的实现细节隐藏起来,让系统更清晰。
缺点
-
增加额外类:
- 引入外观类增加了系统的类数量。
-
过度设计:
- 如果子系统本身不复杂,引入外观类可能是多余的。
适用场景
-
子系统复杂性较高:
- 客户端需要调用多个子系统的接口,外观模式可以简化调用流程。
-
解耦客户端和子系统:
- 客户端通过外观类与子系统交互,降低了直接依赖。
-
为遗留代码提供兼容接口:
- 通过外观模式,可以为复杂的旧系统提供一个简单的接口。
总结
外观模式通过为子系统提供一个统一的接口,简化了客户端与子系统的交互。它适用于需要简化复杂子系统或提供统一访问方式的场景,是一种非常实用的设计模式。