设计模式(C++)-结构型模式-外观模式
一、外观模式概述
外观模式是一种结构型设计模式,它为复杂系统提供一个统一的简化接口,隐藏内部复杂性,让客户端更容易使用系统。
核心思想:简化接口,封装复杂性。外观模式为一组复杂接口提供统一的高层接口,降低使用门槛。
二、外观模式UML类图
2.1 场景:家庭影院系统
一个复杂的家庭影院系统包含多个子系统:DVD播放器、投影仪、音响、灯光、空调等。外观模式将这些复杂的操作简化为几个简单的方法。
三、代码实现
//facade.h/* *外观模式(Facade Pattern)是一种结构型设计模式,它为复杂系统提供一个统一的简化接口, 隐藏内部复杂性,让客户端更容易使用系统。 核心思想:简化接口,封装复杂性。外观模式为一组复杂接口提供统一的高层接口,降低使用门槛。 场景:家庭影院系统 一个复杂的家庭影院系统包含多个子系统:DVD播放器、投影仪、音响、灯光、空调等。 外观模式将这些复杂的操作简化为几个简单的方法。 */#pragmaonce#include<iostream>#include<string>#include<memory>usingnamespacestd;//==============子系统类=================//1.DVD播放器子系统classDVDPlayer{public:voidon();voidoff();voidplay(conststring&movie);voidpuase();voidstop();voidsetSurroundSound();};//2.投影仪子系统classProjector{public:voidon();voidoff();voidsetWideScreenMode();voidsetInput(conststring&source);};//3.音响子系统classAudioSystem{public:voidon();voidoff();voidsetVolume(intlevel);voidsetSurroundMode();voidsetInput(conststring&source);};//4.灯光子系统classLightingSystem{public:voiddim(intlevel);voidon();voidoff();};//5.空调子系统classAirConditioner{public:voidon();voidoff();voidsetTemperature(intdegree);voidsetMode(conststd::string&mode);};//6.家庭影院外观类classHomeTheaterFacade{private:unique_ptr<DVDPlayer>dvd;unique_ptr<Projector>projector;unique_ptr<AudioSystem>audio;unique_ptr<LightingSystem>lights;unique_ptr<AirConditioner>ac;public://构造函数创建所有子系统对象HomeTheaterFacade():dvd(make_unique<DVDPlayer>()),projector(make_unique<Projector>()),audio(make_unique<AudioSystem>()),lights(make_unique<LightingSystem>()),ac(make_unique<AirConditioner>()){}//也可以传入已经存在的子系统对象HomeTheaterFacade(unique_ptr<DVDPlayer>dvd,unique_ptr<Projector>projector,unique_ptr<AudioSystem>audio,unique_ptr<LightingSystem>lights,unique_ptr<AirConditioner>ac):dvd(std::move(dvd)),projector(std::move(projector)),audio(std::move(audio)),lights(std::move(lights)),ac(std::move(ac)){}//简化接口voidwatchMovie(conststring&movie);voidendMovie();voidlistenToMusic(conststring&source);voidshutdownAll();voidadjustLighting(intlevel);voidadjustVolume(intlevel);voidadjustTemperature(intdegree);};voidtestFacade();//facede.cc#include"facade.h"//============DVD播放器子系统==============voidDVDPlayer::on(){cout<<"DVD播放器: 开启\n";}voidDVDPlayer::off(){cout<<"DVD播放器: 关闭\n";}voidDVDPlayer::play(conststring&movie){cout<<"DVD播放器: 播放电影《"<<movie<<"》\n";}voidDVDPlayer::puase(){cout<<"DVD播放器: 暂停\n";}voidDVDPlayer::stop(){cout<<"DVD播放器: 停止\n";}voidDVDPlayer::setSurroundSound(){cout<<"DVD播放器: 启用环绕声\n";}//============投影仪子系统==============voidProjector::on(){cout<<"投影仪: 开启\n";}voidProjector::off(){cout<<"投影仪: 关闭\n";}voidProjector::setWideScreenMode(){cout<<"投影仪: 宽屏模式\n";}voidProjector::setInput(conststring&source){cout<<"投影仪: 输入源设置为 "<<source<<"\n";}//============音响子系统==============voidAudioSystem::on(){cout<<"音响系统: 开启\n";}voidAudioSystem::off(){cout<<"音响系统: 关闭\n";}voidAudioSystem::setVolume(intlevel){cout<<"音响系统: 音量设置为 "<<level<<"\n";}voidAudioSystem::setSurroundMode(){cout<<"音响系统: 环绕声模式\n";}voidAudioSystem::setInput(conststring&source){cout<<"音响系统: 输入源设置为 "<<source<<"\n";}//============灯光子系统==============voidLightingSystem::dim(intlevel){cout<<"灯光系统: 调暗到 "<<level<<"%\n";}voidLightingSystem::on(){cout<<"灯光系统: 开启\n";}voidLightingSystem::off(){cout<<"灯光系统: 关闭\n";}//============空调子系统==============voidAirConditioner::on(){cout<<"空调: 开启\n";}voidAirConditioner::off(){cout<<"空调: 关闭\n";}voidAirConditioner::setTemperature(intdegree){cout<<"空调: 温度设置为 "<<degree<<"°C\n";}voidAirConditioner::setMode(conststd::string&mode){cout<<"空调: 模式设置为 "<<mode<<"\n";}// ====================家庭影院外观类 ====================voidHomeTheaterFacade::watchMovie(conststring&movie){cout<<"\n🎬 准备观看电影: "<<movie<<"\n";cout<<"================================\n";//按照正确顺序启动所有设备lights->dim(10);//调暗灯光projector->on();//打开投影仪projector->setInput("DVD");projector->setWideScreenMode();audio->on();// 打开音响audio->setInput("DVD");audio->setSurroundMode();audio->setVolume(20);dvd->on();// 打开DVDdvd->setSurroundSound();dvd->play(movie);ac->on();// 打开空调ac->setTemperature(24);ac->setMode("舒适");cout<<"✅ 家庭影院准备就绪,开始观影!\n";}voidHomeTheaterFacade::endMovie(){cout<<"\n⏹️ 结束观影\n";cout<<"================================\n";dvd->stop();dvd->off();audio->setVolume(0);audio->off();projector->off();lights->on();// 恢复灯光lights->dim(80);cout<<"✅ 设备已关闭\n";}voidHomeTheaterFacade::listenToMusic(conststring&source){cout<<"\n🎵 听音乐模式\n";cout<<"================================\n";lights->dim(30);audio->on();audio->setInput(source);audio->setVolume(15);ac->on();ac->setTemperature(25);cout<<"✅ 音乐模式准备就绪\n";}voidHomeTheaterFacade::shutdownAll(){cout<<"\n🔌 关闭所有设备\n";cout<<"================================\n";dvd->off();projector->off();audio->off();lights->off();ac->off();cout<<"✅ 所有设备已关闭\n";}voidHomeTheaterFacade::adjustLighting(intlevel){lights->dim(level);}voidHomeTheaterFacade::adjustVolume(intlevel){audio->setVolume(level);}voidHomeTheaterFacade::adjustTemperature(intdegree){ac->setTemperature(degree);}voidtestFacade(){cout<<"=================Facade start==============="<<endl;cout<<"🏠 家庭影院系统演示\n";cout<<"==================\n";// 方式1:外观类负责创建所有子系统HomeTheaterFacade theater;// 使用简化接口theater.watchMovie("阿凡达");theater.adjustVolume(25);// 可以单独调整theater.endMovie();// 使用其他模式theater.listenToMusic("蓝牙");theater.shutdownAll();std::cout<<"\n\n";// 方式2:依赖注入方式cout<<"🎯 依赖注入方式演示\n";cout<<"==================\n";autocustomDVD=std::make_unique<DVDPlayer>();autocustomProj=std::make_unique<Projector>();autocustomAudio=std::make_unique<AudioSystem>();autocustomLights=std::make_unique<LightingSystem>();autocustomAC=std::make_unique<AirConditioner>();HomeTheaterFacadecustomTheater(std::move(customDVD),std::move(customProj),std::move(customAudio),std::move(customLights),std::move(customAC));customTheater.watchMovie("星际穿越");customTheater.endMovie();cout<<"=================Facade End==============="<<endl;}四、优缺点总结
优点:
- 简化使用:客户端只需要调用少数方法
- 降低耦合:客户端与子系统解耦
- 提高可维护性:子系统变化不影响客户端
- 层次化结构:可以定义多层外观
缺点
- 可能转换为上帝对象:外观类承担过多责任
- 新增依赖:客户端依赖外观,而非直接子系统
- 可能隐藏功能:过度简化可能丢失高级功能