外观模式是一种结构型设计模式,它通过提供一个统一的接口来访问子系统中的一组接口,从而简化了客户端与复杂子系统的交互。通过外观模式,客户端只需要通过一个简单的接口就能和复杂的子系统进行交互,而不用关心子系统的内部细节。
生活中的实例:家庭影院系统
背景
想象一下,你拥有一个高端家庭影院系统,但它由多个子系统组成,比如电视、音响、DVD 播放器、投影仪、灯光控制等等。每个子系统都有自己复杂的操作界面,如果每次看电影都需要你分别开启和调整这些设备,会非常麻烦且耗时。这时,我们可以使用外观模式来简化这一过程。
实现外观模式
子系统类
首先,我们定义每个子系统,以及它们的具体操作
#include <iostream>
#include <string>
// 电视子系统
class TV {
public:
void on() {
std::cout << "TV is On" << std::endl;
}
void off() {
std::cout << "TV is Off" << std::endl;
}
};
// 音响子系统
class SoundSystem {
public:
void on() {
std::cout << "Sound System is On" << std::endl;
}
void setVolume(int level) {
std::cout << "Volume set to " << level << std::endl;
}
void off() {
std::cout << "Sound System is Off" << std::endl;
}
};
// DVD 播放器子系统
class DVDPlayer {
public:
void on() {
std::cout << "DVD Player is On" << std::endl;
}
void play(const std::string& movie) {
std::cout << "Playing movie: " << movie << std::endl;
}
void off() {
std::cout << "DVD Player is Off" << std::endl;
}
};
// 灯光控制子系统
class Lights {
public:
void dim(int level) {
std::cout << "Lights dimmed to " << level << "%" << std::endl;
}
};
为了更方便用户操作,我们创建了一个家庭影院外观类,以便控制所有这些子系统。
外观类
class HomeTheaterFacade {
private:
TV* tv;
SoundSystem* soundSystem;
DVDPlayer* dvdPlayer;
Lights* lights;
public:
HomeTheaterFacade(TV* tv, SoundSystem* soundSystem, DVDPlayer* dvdPlayer, Lights* lights)
: tv(tv), soundSystem(soundSystem), dvdPlayer(dvdPlayer), lights(lights) {}
// 观影前的准备
void watchMovie(const std::string& movie) {
std::cout << "Preparing to watch a movie..." << std::endl;
lights->dim(10); // 调暗灯光
tv->on(); // 开电视
soundSystem->on(); // 开音响
soundSystem->setVolume(15); // 设置音量
dvdPlayer->on(); // 开 DVD 播放器
dvdPlayer->play(movie); // 播放电影
}
// 观影结束后关闭所有设备
void endMovie() {
std::cout << "Shutting movie theater down..." << std::endl;
tv->off();
soundSystem->off();
dvdPlayer->off();
lights->dim(100); // 恢复灯光
}
};
使用示例
int main() {
// 创建各个子系统的对象
TV tv;
SoundSystem soundSystem;
DVDPlayer dvdPlayer;
Lights lights;
// 创建外观对象,将子系统对象传递进去
HomeTheaterFacade homeTheater(&tv, &soundSystem, &dvdPlayer, &lights);
// 使用外观模式控制家庭影院系统
homeTheater.watchMovie("Inception");
std::cout << "Enjoy the movie!" << std::endl;
// 观影结束后关闭系统
homeTheater.endMovie();
return 0;
}
完整代码
#include <iostream>
#include <string>
// 电视子系统
class TV {
public:
void on() {
std::cout << "TV is On" << std::endl;
}
void off() {
std::cout << "TV is Off" << std::endl;
}
};
// 音响子系统
class SoundSystem {
public:
void on() {
std::cout << "Sound System is On" << std::endl;
}
void setVolume(int level) {
std::cout << "Volume set to " << level << std::endl;
}
void off() {
std::cout << "Sound System is Off" << std::endl;
}
};
// DVD 播放器子系统
class DVDPlayer {
public:
void on() {
std::cout << "DVD Player is On" << std::endl;
}
void play(const std::string& movie) {
std::cout << "Playing movie: " << movie << std::endl;
}
void off() {
std::cout << "DVD Player is Off" << std::endl;
}
};
// 灯光控制子系统
class Lights {
public:
void dim(int level) {
std::cout << "Lights dimmed to " << level << "%" << std::endl;
}
};
// 外观类
class HomeTheaterFacade {
private:
TV* tv;
SoundSystem* soundSystem;
DVDPlayer* dvdPlayer;
Lights* lights;
public:
HomeTheaterFacade(TV* tv, SoundSystem* soundSystem, DVDPlayer* dvdPlayer, Lights* lights)
: tv(tv), soundSystem(soundSystem), dvdPlayer(dvdPlayer), lights(lights) {}
// 观影前的准备
void watchMovie(const std::string& movie) {
std::cout << "Preparing to watch a movie..." << std::endl;
lights->dim(10); // 调暗灯光
tv->on(); // 开电视
soundSystem->on(); // 开音响
soundSystem->setVolume(15); // 设置音量
dvdPlayer->on(); // 开 DVD 播放器
dvdPlayer->play(movie); // 播放电影
}
// 观影结束后关闭所有设备
void endMovie() {
std::cout << "Shutting movie theater down..." << std::endl;
tv->off();
soundSystem->off();
dvdPlayer->off();
lights->dim(100); // 恢复灯光
}
};
int main() {
// 创建各个子系统的对象
TV tv;
SoundSystem soundSystem;
DVDPlayer dvdPlayer;
Lights lights;
// 创建外观对象,将子系统对象传递进去
HomeTheaterFacade homeTheater(&tv, &soundSystem, &dvdPlayer, &lights);
// 使用外观模式控制家庭影院系统
homeTheater.watchMovie("Inception");
std::cout << "Enjoy the movie!" << std::endl;
// 观影结束后关闭系统
homeTheater.endMovie();
return 0;
}
总结
通过使用外观模式,在家庭影院这个例子中,我们将多个复杂的子系统操作封装在一个简单的接口中。用户只需要通过这个接口(HomeTheaterFacade
类)就可以很方便地控制整个系统,而不需要了解每个子系统的具体细节。这种方式在简化客户端操作的同时,也提高了系统的可维护性。