C++设计模式外观模式(Facade)(家庭影院案例)

1. 什么是外观模式?

外观模式(Facade Pattern)是一种结构型设计模式 ,它提供了一个统一的接口,让客户端可以通过这个接口与系统内部的多个子系统交互,而不需要了解内部的复杂实现逻辑。

通俗解释:

外观模式就像"总开关"或"遥控器",你不需要逐一操作每个设备,而是通过一个简单的接口,轻松控制复杂系统。


2. 外观模式的设计结构

  1. 外观类(Facade): 提供一个统一接口,屏蔽内部复杂逻辑。
  2. 子系统(Subsystem): 负责具体功能的实现,外观类会调用它们。
  3. 客户端(Client): 通过外观类与子系统交互,不直接接触子系统。

3. 外观模式案例:家庭影院

场景: 假设我们有一个家庭影院系统,包括播放器、投影仪、音响和灯光系统。每个设备都有自己的操作方法,使用时需要逐个操作。这显然不方便。

现在我们用外观模式,提供一个**"一键启动""一键关闭"**的功能,让整个操作变得简单。


代码实现

代码描述
  • 子系统类: 定义家庭影院中的播放器、投影仪、音响和灯光系统,它们负责具体的操作。
  • 外观类: 提供startMovie()stopMovie()两个简单接口,一键操作所有子系统。
  • 客户端: 只调用外观类提供的接口。

完整代码
cpp 复制代码
#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. 详细解读

  1. 子系统类的职责:

    • 每个子系统(播放器、投影仪、音响、灯光)都实现了自己的具体功能,比如打开设备、设置模式、调整音量等。
  2. 外观类的作用:

    • 外观类HomeTheaterFacade将这些子系统的复杂操作封装成两个方法:startMovie()stopMovie()。客户端只需要调用这两个方法,而不需要知道内部的细节。
  3. 客户端的简化:

    • 客户端只需创建外观类对象,并调用简单的接口即可完成复杂的操作逻辑。
    • 如果没有外观模式,客户端需要逐一调用每个子系统的接口,会非常繁琐。

6. 优点总结

  1. 简化接口: 客户端不需要了解多个子系统的复杂操作。
  2. 降低耦合: 外观类与子系统解耦,子系统的变化不会影响客户端。
  3. 易于扩展: 如果增加新的子系统(比如空调),只需修改外观类,不影响客户端。

7. 扩展案例:增加空调系统

如果家庭影院中新增一个"空调系统",只需要增加子系统类,并修改外观类即可:

新增代码:
cpp 复制代码
// **子系统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;
    }
};

总结

外观模式通过封装复杂系统的内部逻辑,为客户端提供了简单易用的接口,极大地提高了系统的可维护性和可扩展性。这个案例完整地展示了外观模式的应用场景和优点,非常适合复杂系统的模块化管理。

相关推荐
Crazy learner37 分钟前
C 和 C++ 动态库的跨语言调用原理
c语言·c++
金士顿4 小时前
MFC 文档模板 每个文档模板需要实例化吧
c++·mfc
人才程序员7 小时前
QML z轴(z-order)前后层级
c语言·前端·c++·qt·软件工程·用户界面·界面
w(゚Д゚)w吓洗宝宝了7 小时前
C vs C++: 一场编程语言的演变与对比
c语言·开发语言·c++
小老鼠不吃猫8 小时前
C++点云大文件读取
开发语言·c++
姚先生979 小时前
LeetCode 35. 搜索插入位置 (C++实现)
c++·算法·leetcode
NorthCastle9 小时前
设计模式-创建型模式-简单工厂模式详解
设计模式·简单工厂模式
CoderCodingNo9 小时前
【GESP】C++二级考试大纲知识点梳理, (4)流程图
开发语言·c++·流程图
小小unicorn10 小时前
【C++初阶】STL详解(十三)—— 用一个哈希表同时封装出unordered_map和unordered_set
java·c++·散列表
慕羽★10 小时前
详细介绍如何使用rapidjson读取json文件
linux·c++·windows·json·file·param·rapidjson