设计模式(C++)-结构型模式-外观模式
一、外观模式概述
外观模式是一种结构型设计模式,它为复杂系统提供一个统一的简化接口,隐藏内部复杂性,让客户端更容易使用系统。
核心思想:简化接口,封装复杂性。外观模式为一组复杂接口提供统一的高层接口,降低使用门槛。
二、外观模式UML类图
2.1 场景:家庭影院系统
一个复杂的家庭影院系统包含多个子系统:DVD播放器、投影仪、音响、灯光、空调等。外观模式将这些复杂的操作简化为几个简单的方法。

三、代码实现
cpp
//facade.h
/*
*外观模式(Facade Pattern)是一种结构型设计模式,它为复杂系统提供一个统一的简化接口,
隐藏内部复杂性,让客户端更容易使用系统。
核心思想:简化接口,封装复杂性。外观模式为一组复杂接口提供统一的高层接口,降低使用门槛。
场景:家庭影院系统
一个复杂的家庭影院系统包含多个子系统:DVD播放器、投影仪、音响、灯光、空调等。
外观模式将这些复杂的操作简化为几个简单的方法。
*/
#pragma once
#include <iostream>
#include <string>
#include <memory>
using namespace std;
//==============子系统类=================
//1.DVD播放器子系统
class DVDPlayer {
public:
void on();
void off();
void play(const string&movie);
void puase();
void stop();
void setSurroundSound();
};
//2.投影仪子系统
class Projector {
public:
void on();
void off();
void setWideScreenMode();
void setInput(const string&source);
};
//3.音响子系统
class AudioSystem {
public:
void on();
void off();
void setVolume(int level);
void setSurroundMode();
void setInput(const string&source);
};
//4.灯光子系统
class LightingSystem {
public:
void dim(int level);
void on();
void off();
};
//5.空调子系统
class AirConditioner {
public:
void on();
void off();
void setTemperature(int degree);
void setMode(const std::string&mode);
};
//6.家庭影院外观类
class HomeTheaterFacade {
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)) {}
//简化接口
void watchMovie(const string&movie);
void endMovie();
void listenToMusic(const string&source);
void shutdownAll();
void adjustLighting(int level);
void adjustVolume(int level);
void adjustTemperature(int degree);
};
void testFacade();
//facede.cc
#include "facade.h"
//============DVD播放器子系统==============
void DVDPlayer::on() {
cout << "DVD播放器: 开启\n";
}
void DVDPlayer::off() {
cout << "DVD播放器: 关闭\n";
}
void DVDPlayer::play(const string&movie) {
cout << "DVD播放器: 播放电影《" << movie << "》\n";
}
void DVDPlayer::puase() {
cout << "DVD播放器: 暂停\n";
}
void DVDPlayer::stop() {
cout << "DVD播放器: 停止\n";
}
void DVDPlayer::setSurroundSound() {
cout << "DVD播放器: 启用环绕声\n";
}
//============投影仪子系统==============
void Projector::on() {
cout << "投影仪: 开启\n";
}
void Projector::off() {
cout << "投影仪: 关闭\n";
}
void Projector::setWideScreenMode() {
cout << "投影仪: 宽屏模式\n";
}
void Projector::setInput(const string&source) {
cout << "投影仪: 输入源设置为 " << source << "\n";
}
//============音响子系统==============
void AudioSystem::on() {
cout << "音响系统: 开启\n";
}
void AudioSystem::off() {
cout << "音响系统: 关闭\n";
}
void AudioSystem::setVolume(int level) {
cout << "音响系统: 音量设置为 " << level << "\n";
}
void AudioSystem::setSurroundMode() {
cout << "音响系统: 环绕声模式\n";
}
void AudioSystem::setInput(const string&source) {
cout << "音响系统: 输入源设置为 " << source << "\n";
}
//============灯光子系统==============
void LightingSystem::dim(int level) {
cout << "灯光系统: 调暗到 " << level << "%\n";
}
void LightingSystem::on() {
cout << "灯光系统: 开启\n";
}
void LightingSystem::off() {
cout << "灯光系统: 关闭\n";
}
//============空调子系统==============
void AirConditioner::on() {
cout << "空调: 开启\n";
}
void AirConditioner::off() {
cout << "空调: 关闭\n";
}
void AirConditioner::setTemperature(int degree) {
cout << "空调: 温度设置为 " << degree << "°C\n";
}
void AirConditioner::setMode(const std::string&mode) {
cout << "空调: 模式设置为 " << mode << "\n";
}
// ====================家庭影院外观类 ====================
void HomeTheaterFacade::watchMovie(const string&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(); // 打开DVD
dvd->setSurroundSound();
dvd->play(movie);
ac->on(); // 打开空调
ac->setTemperature(24);
ac->setMode("舒适");
cout << "✅ 家庭影院准备就绪,开始观影!\n";
}
void HomeTheaterFacade::endMovie() {
cout << "\n⏹️ 结束观影\n";
cout << "================================\n";
dvd->stop();
dvd->off();
audio->setVolume(0);
audio->off();
projector->off();
lights->on(); // 恢复灯光
lights->dim(80);
cout << "✅ 设备已关闭\n";
}
void HomeTheaterFacade::listenToMusic(const string&source) {
cout << "\n🎵 听音乐模式\n";
cout << "================================\n";
lights->dim(30);
audio->on();
audio->setInput(source);
audio->setVolume(15);
ac->on();
ac->setTemperature(25);
cout << "✅ 音乐模式准备就绪\n";
}
void HomeTheaterFacade::shutdownAll() {
cout << "\n🔌 关闭所有设备\n";
cout << "================================\n";
dvd->off();
projector->off();
audio->off();
lights->off();
ac->off();
cout << "✅ 所有设备已关闭\n";
}
void HomeTheaterFacade::adjustLighting(int level) {
lights->dim(level);
}
void HomeTheaterFacade::adjustVolume(int level) {
audio->setVolume(level);
}
void HomeTheaterFacade::adjustTemperature(int degree) {
ac->setTemperature(degree);
}
void testFacade() {
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";
auto customDVD = std::make_unique<DVDPlayer>();
auto customProj = std::make_unique<Projector>();
auto customAudio = std::make_unique<AudioSystem>();
auto customLights = std::make_unique<LightingSystem>();
auto customAC = std::make_unique<AirConditioner>();
HomeTheaterFacade customTheater(
std::move(customDVD),
std::move(customProj),
std::move(customAudio),
std::move(customLights),
std::move(customAC)
);
customTheater.watchMovie("星际穿越");
customTheater.endMovie();
cout << "=================Facade End===============" << endl;
}
四、优缺点总结
优点:
- 简化使用:客户端只需要调用少数方法
- 降低耦合:客户端与子系统解耦
- 提高可维护性:子系统变化不影响客户端
- 层次化结构:可以定义多层外观
缺点
- 可能转换为上帝对象:外观类承担过多责任
- 新增依赖:客户端依赖外观,而非直接子系统
- 可能隐藏功能:过度简化可能丢失高级功能