1. 什么是外观模式?
外观模式(Facade Pattern)是一种结构型设计模式,它提供了一个统一的接口,让客户端可以通过这个接口与系统内部的多个子系统交互,而不需要了解内部的复杂实现逻辑。
通俗解释:
外观模式就像“总开关”或“遥控器”,你不需要逐一操作每个设备,而是通过一个简单的接口,轻松控制复杂系统。
2. 外观模式的设计结构
- 外观类(Facade): 提供一个统一接口,屏蔽内部复杂逻辑。
- 子系统(Subsystem): 负责具体功能的实现,外观类会调用它们。
- 客户端(Client): 通过外观类与子系统交互,不直接接触子系统。
3. 外观模式案例:家庭影院
场景: 假设我们有一个家庭影院系统,包括播放器、投影仪、音响和灯光系统。每个设备都有自己的操作方法,使用时需要逐个操作。这显然不方便。
现在我们用外观模式,提供一个**“一键启动”和“一键关闭”**的功能,让整个操作变得简单。
代码实现
代码描述
- 子系统类: 定义家庭影院中的播放器、投影仪、音响和灯光系统,它们负责具体的操作。
- 外观类: 提供
startMovie()
和stopMovie()
两个简单接口,一键操作所有子系统。 - 客户端: 只调用外观类提供的接口。
完整代码
#include <iostream>
#include <string>
using namespace std;
// **子系统1:播放器**
class Player {
public:
void turnOn() {
cout << "播放器:已打开。" << endl;
}
void turnOff() {
cout << "播放器:已关闭。" << endl;
}
void playMovie(const string& movie) {
cout << "播放器:正在播放电影《" << movie << "》。" << endl;
}
};
// **子系统2:投影仪**
class Projector {
public:
void turnOn() {
cout << "投影仪:已打开。" << endl;
}
void turnOff() {
cout << "投影仪:已关闭。" << endl;
}
void setMode(const string& mode) {
cout << "投影仪:模式设置为" << mode << "。" << endl;
}
};
// **子系统3:音响**
class SoundSystem {
public:
void turnOn() {
cout << "音响:已打开。" << endl;
}
void turnOff() {
cout << "音响:已关闭。" << endl;
}
void setVolume(int level) {
cout << "音响:音量设置为" << level << "。" << endl;
}
};
// **子系统4:灯光**
class LightSystem {
public:
void dimLights() {
cout << "灯光系统:灯光已调暗。" << endl;
}
void brightenLights() {
cout << "灯光系统:灯光已恢复正常。" << endl;
}
};
// **外观类:家庭影院外观**
class HomeTheaterFacade {
private:
Player player;
Projector projector;
SoundSystem soundSystem;
LightSystem lightSystem;
public:
HomeTheaterFacade() {}
// 一键启动家庭影院
void startMovie(const string& movie) {
cout << "正在启动家庭影院系统..." << endl;
lightSystem.dimLights();
player.turnOn();
projector.turnOn();
projector.setMode("影院模式");
soundSystem.turnOn();
soundSystem.setVolume(50);
player.playMovie(movie);
cout << "家庭影院已准备好,享受您的电影吧!" << endl;
}
// 一键关闭家庭影院
void stopMovie() {
cout << "正在关闭家庭影院系统..." << endl;
player.turnOff();
projector.turnOff();
soundSystem.turnOff();
lightSystem.brightenLights();
cout << "家庭影院系统已关闭。" << endl;
}
};
// **客户端:调用外观类**
int main() {
HomeTheaterFacade homeTheater;
cout << "### 开始观看电影 ###" << endl;
homeTheater.startMovie("盗梦空间");
cout << "\n### 停止观看电影 ###" << endl;
homeTheater.stopMovie();
return 0;
}
4. 运行结果
### 开始观看电影 ###
正在启动家庭影院系统...
灯光系统:灯光已调暗。
播放器:已打开。
投影仪:已打开。
投影仪:模式设置为影院模式。
音响:已打开。
音响:音量设置为50。
播放器:正在播放电影《盗梦空间》。
家庭影院已准备好,享受您的电影吧!
### 停止观看电影 ###
正在关闭家庭影院系统...
播放器:已关闭。
投影仪:已关闭。
音响:已关闭。
灯光系统:灯光已恢复正常。
家庭影院系统已关闭。
5. 详细解读
子系统类的职责:
- 每个子系统(播放器、投影仪、音响、灯光)都实现了自己的具体功能,比如打开设备、设置模式、调整音量等。
外观类的作用:
- 外观类
HomeTheaterFacade
将这些子系统的复杂操作封装成两个方法:startMovie()
和stopMovie()
。客户端只需要调用这两个方法,而不需要知道内部的细节。
- 外观类
客户端的简化:
- 客户端只需创建外观类对象,并调用简单的接口即可完成复杂的操作逻辑。
- 如果没有外观模式,客户端需要逐一调用每个子系统的接口,会非常繁琐。
6. 优点总结
- 简化接口: 客户端不需要了解多个子系统的复杂操作。
- 降低耦合: 外观类与子系统解耦,子系统的变化不会影响客户端。
- 易于扩展: 如果增加新的子系统(比如空调),只需修改外观类,不影响客户端。
7. 扩展案例:增加空调系统
如果家庭影院中新增一个“空调系统”,只需要增加子系统类,并修改外观类即可:
新增代码:
// **子系统5:空调**
class AirConditioner {
public:
void turnOn() {
cout << "空调:已打开。" << endl;
}
void turnOff() {
cout << "空调:已关闭。" << endl;
}
void setTemperature(int temp) {
cout << "空调:温度设置为" << temp << "度。" << endl;
}
};
// 在外观类中添加空调的逻辑
class HomeTheaterFacade {
private:
Player player;
Projector projector;
SoundSystem soundSystem;
LightSystem lightSystem;
AirConditioner airConditioner;
public:
void startMovie(const string& movie) {
cout << "正在启动家庭影院系统..." << endl;
lightSystem.dimLights();
airConditioner.turnOn();
airConditioner.setTemperature(22);
player.turnOn();
projector.turnOn();
projector.setMode("影院模式");
soundSystem.turnOn();
soundSystem.setVolume(50);
player.playMovie(movie);
cout << "家庭影院已准备好,享受您的电影吧!" << endl;
}
void stopMovie() {
cout << "正在关闭家庭影院系统..." << endl;
player.turnOff();
projector.turnOff();
soundSystem.turnOff();
airConditioner.turnOff();
lightSystem.brightenLights();
cout << "家庭影院系统已关闭。" << endl;
}
};
总结
外观模式通过封装复杂系统的内部逻辑,为客户端提供了简单易用的接口,极大地提高了系统的可维护性和可扩展性。这个案例完整地展示了外观模式的应用场景和优点,非常适合复杂系统的模块化管理。