C++设计模式之外观模式详解
外观模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易被使用。这种模式通过引入一个外观角色来简化客户端与子系统之间的交互,客户端只需与外观角色打交道,而无需了解子系统内部的复杂结构。
·
外观模式(Facade Pattern)是一种结构型设计模式,它为子系统中的一组接口提供一个统一的高层接口,使得子系统更容易被使用。这种模式通过引入一个外观角色来简化客户端与子系统之间的交互,客户端只需与外观角色打交道,而无需了解子系统内部的复杂结构。
外观模式的核心角色
- 外观(Facade):提供一个统一的接口,封装子系统的复杂性
- 子系统(Subsystem):由多个相关联的类组成,实现具体功能
- 客户端(Client):通过外观接口与子系统交互,无需了解子系统细节
外观模式的实现示例
下面以"家庭影院系统"为例展示外观模式的实现,家庭影院包含投影仪、音响、DVD播放器等多个设备,外观模式可以简化这些设备的协同操作:
#include <iostream>
#include <string>
// 子系统:投影仪
class Projector {
public:
void on() {
std::cout << "投影仪已开启" << std::endl;
}
void off() {
std::cout << "投影仪已关闭" << std::endl;
}
void setInput(const std::string& source) {
std::cout << "投影仪输入源设置为: " << source << std::endl;
}
void setResolution(const std::string& resolution) {
std::cout << "投影仪分辨率设置为: " << resolution << std::endl;
}
};
// 子系统:音响
class SoundSystem {
public:
void on() {
std::cout << "音响系统已开启" << std::endl;
}
void off() {
std::cout << "音响系统已关闭" << std::endl;
}
void setVolume(int level) {
std::cout << "音响音量设置为: " << level << std::endl;
}
void setSurroundSound(bool enable) {
if (enable) {
std::cout << "环绕声已开启" << std::endl;
} else {
std::cout << "环绕声已关闭" << std::endl;
}
}
};
// 子系统:DVD播放器
class DvdPlayer {
private:
std::string currentMovie;
public:
void on() {
std::cout << "DVD播放器已开启" << std::endl;
}
void off() {
std::cout << "DVD播放器已关闭" << std::endl;
}
void play(const std::string& movie) {
currentMovie = movie;
std::cout << "正在播放电影: " << currentMovie << std::endl;
}
void pause() {
std::cout << "电影 " << currentMovie << " 已暂停" << std::endl;
}
void stop() {
std::cout << "电影 " << currentMovie << " 已停止" << std::endl;
}
};
// 外观类:家庭影院外观
class HomeTheaterFacade {
private:
Projector* projector;
SoundSystem* soundSystem;
DvdPlayer* dvdPlayer;
public:
// 初始化所有子系统
HomeTheaterFacade(Projector* p, SoundSystem* s, DvdPlayer* d)
: projector(p), soundSystem(s), dvdPlayer(d) {}
// 简化接口:准备播放电影
void watchMovie(const std::string& movie) {
std::cout << "\n=== 准备播放电影 ===" << std::endl;
projector->on();
projector->setInput("DVD");
projector->setResolution("4K");
soundSystem->on();
soundSystem->setVolume(8);
soundSystem->setSurroundSound(true);
dvdPlayer->on();
dvdPlayer->play(movie);
}
// 简化接口:暂停电影
void pauseMovie() {
std::cout << "\n=== 暂停电影 ===" << std::endl;
dvdPlayer->pause();
}
// 简化接口:结束电影
void endMovie() {
std::cout << "\n=== 结束电影 ===" << std::endl;
dvdPlayer->stop();
dvdPlayer->off();
soundSystem->off();
projector->off();
}
};
// 客户端使用
int main() {
// 创建子系统对象
Projector* projector = new Projector();
SoundSystem* soundSystem = new SoundSystem();
DvdPlayer* dvdPlayer = new DvdPlayer();
// 创建外观对象
HomeTheaterFacade* homeTheater = new HomeTheaterFacade(projector, soundSystem, dvdPlayer);
// 客户端通过外观接口操作复杂的子系统
homeTheater->watchMovie("星际穿越");
homeTheater->pauseMovie();
homeTheater->watchMovie("星际穿越"); // 继续播放
homeTheater->endMovie();
// 清理资源
delete homeTheater;
delete dvdPlayer;
delete soundSystem;
delete projector;
return 0;
}
外观模式的工作原理
- 外观类封装了多个子系统的交互细节,提供简洁的高层接口
- 客户端只需调用外观类的方法,无需直接操作子系统
- 外观类负责协调多个子系统的调用顺序和交互方式
- 子系统之间可以相互交互,但客户端无需了解这些细节
外观模式与中介者模式的区别
- 外观模式:关注简化客户端与子系统的交互,子系统之间可以直接通信
- 中介者模式:关注子系统之间的通信,子系统通过中介者间接通信
外观模式的应用场景
- 当需要简化复杂子系统的使用时
- 当需要为一个复杂的子系统提供一个统一接口时
- 当需要隔离客户端与子系统,减少它们之间的依赖时
- 在分层架构中,可以为各层提供外观接口,简化层间交互
外观模式的优缺点
优点:
- 简化了客户端与子系统的交互,减少了客户端需要了解的类和方法
- 降低了客户端与子系统之间的耦合度,提高了系统的可维护性
- 有利于子系统的扩展和复用
- 可以有多个外观类,分别针对不同场景提供接口
缺点:
- 外观类可能会变得过于庞大,承担过多责任,违背单一职责原则
- 新增子系统功能可能需要修改外观类,违反开放-封闭原则
- 可能隐藏了子系统的灵活性,限制了高级用户对系统的定制
外观模式在C++标准库中也有体现,例如std::iostream就是std::istream和std::ostream等底层流类的外观,为复杂的输入输出操作提供了简单统一的接口。在大型框架中,外观模式也被广泛用于提供简洁的API入口。
更多推荐
所有评论(0)