09.C++设计模式-外观模式

1. 模式定义

外观模式(Facade Pattern) 为子系统中的一组接口提供一个统一的简化接口。它定义了一个高层接口,使子系统更容易使用。

2. 核心思想

  • 封装复杂的子系统内部逻辑
  • 提供简化的客户端调用接口
  • 降低客户端与子系统的耦合度

3. 逻辑结构图

Facade
+operation()
SubsystemA
+operationA()
SubsystemB
+operationB()
SubsystemC
+operationC()
Client
+main()

4. 应用场景

典型场景:
  1. 复杂系统的简化访问

    • 编译器系统(词法分析、语法分析、代码生成)
    • 视频转换工具(解码、编码、混流)
  2. 分层系统的入口

    • 业务逻辑层对数据访问层的封装
    • 服务层对多个DAO的协调
  3. 遗留系统适配

    • 为新系统提供统一接口
    • 隔离旧系统的复杂调用
  4. 第三方库封装

    • 简化第三方API调用
    • 替换第三方库时减少影响

5. C++代码示例

场景:家庭影院系统
cpp 复制代码
#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;
    }
};

// 子系统类:音响系统
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 setMode(const std::string& mode) {
        std::cout << "音效模式: " << mode << std::endl;
    }
};

// 子系统类:蓝光播放器
class BluRayPlayer {
public:
    void on() { std::cout << "蓝光播放器已打开" << std::endl; }
    void off() { std::cout << "蓝光播放器已关闭" << std::endl; }
    void play(const std::string& movie) {
        std::cout << "正在播放电影: " << movie << std::endl;
    }
    void stop() { std::cout << "停止播放" << std::endl; }
};

// 子系统类:灯光系统
class Lighting {
public:
    void dim(int level) {
        std::cout << "灯光亮度调至: " << level << "%" << std::endl;
    }
    void on() { std::cout << "灯光已打开" << std::endl; }
};

// 外观类:家庭影院外观
class HomeTheaterFacade {
private:
    Projector* projector;
    SoundSystem* soundSystem;
    BluRayPlayer* bluRayPlayer;
    Lighting* lighting;
    
public:
    HomeTheaterFacade(Projector* proj, SoundSystem* sound, 
                      BluRayPlayer* bluray, Lighting* light)
        : projector(proj), soundSystem(sound), 
          bluRayPlayer(bluray), lighting(light) {}
    
    // 简化的观影模式
    void watchMovie(const std::string& movie) {
        std::cout << "\n=== 准备观影模式 ===" << std::endl;
        lighting->dim(20);           // 调暗灯光
        projector->on();              // 打开投影
        projector->setInput("BluRay"); // 设置输入源
        soundSystem->on();            // 打开音响
        soundSystem->setVolume(30);   // 设置音量
        soundSystem->setMode("影院");
        bluRayPlayer->on();           // 打开播放器
        bluRayPlayer->play(movie);    // 播放电影
        std::cout << "=== 开始观影 ===\n" << std::endl;
    }
    
    // 简化的结束观影
    void endMovie() {
        std::cout << "\n=== 结束观影 ===" << std::endl;
        bluRayPlayer->stop();         // 停止播放
        bluRayPlayer->off();          // 关闭播放器
        soundSystem->off();           // 关闭音响
        projector->off();             // 关闭投影
        lighting->on();               // 打开灯光
        std::cout << "=== 观影结束 ===\n" << std::endl;
    }
};

// 客户端代码
int main() {
    // 创建子系统对象
    Projector projector;
    SoundSystem soundSystem;
    BluRayPlayer bluRayPlayer;
    Lighting lighting;
    
    // 创建外观对象
    HomeTheaterFacade homeTheater(&projector, &soundSystem, 
                                   &bluRayPlayer, &lighting);
    
    // 客户端只需调用简化接口
    homeTheater.watchMovie("盗梦空间");
    homeTheater.endMovie();
    
    return 0;
}

6. 执行流程时序图

Lighting BluRayPlayer SoundSystem Projector Facade Client Lighting BluRayPlayer SoundSystem Projector Facade Client watchMovie("盗梦空间") dim(20) on() setInput("BluRay") on() setVolume(30) setMode("影院") on() play("盗梦空间") 准备就绪

7. 优缺点分析

优点

简化调用 :客户端只需与外观交互,无需了解子系统细节

降低耦合 :客户端与子系统的依赖关系减弱

提高灵活性 :子系统内部变化不影响客户端

分层清晰:为复杂系统提供明确的分层边界

缺点

可能违背开闭原则 :新增子系统可能需要修改外观类

可能成为上帝对象 :外观类可能过度集中功能

性能开销:增加一层间接调用

8. 与其他模式的关系

  • 外观模式 vs 适配器模式

    • 外观:提供新接口简化调用
    • 适配器:转换接口使不兼容的类能协作
  • 外观模式 vs 中介者模式

    • 外观:单向调用,客户端→外观→子系统
    • 中介者:双向协作,各组件通过中介通信

9. 最佳实践建议

  1. 按功能维度封装:一个外观类负责一组相关操作
  2. 避免外观类过于庞大:考虑拆分成多个外观类
  3. 可选择是否暴露子系统:高级用户可直接调用子系统
  4. 配合单例模式:外观类通常设计为单例

10. 实际应用示例

cpp 复制代码
// 游戏引擎中的外观模式应用
class GameEngine {
public:
    void startGame() {
        graphics.init();
        physics.init();
        audio.init();
        input.init();
        // 复杂的初始化流程...
    }
    
    void update(float deltaTime) {
        input.process();
        physics.update(deltaTime);
        graphics.render();
        audio.update();
    }
};

外观模式特别适合在系统重构、框架设计、第三方库集成等场景中使用,能够有效提升代码的可维护性和可读性。

相关推荐
晚会者荣1 小时前
C++11_3:包装器,智能指针
c++
handler011 小时前
TCP(传输控制协议)核心机制与底层原理
linux·网络·c++·笔记·网络协议·tcp/ip·操作系统
王老师青少年编程1 小时前
csp信奥赛C++高频考点专项训练之字符串 --【字符串综合】:遍历问题
c++·字符串·csp·高频考点·信奥赛
yoyo_zzm1 小时前
五大编程语言对比:PHP、C、C++、C#、易语言
c语言·c++·php
杰之行1 小时前
Fast-DDS Transport 层架构详解
c++·人工智能
W23035765731 小时前
Linux C++ 基于 timerfd + epoll 实现高性能定时器队列(完整源码 + 超详细解析)
linux·开发语言·c++·线程池
Lochor Lee1 小时前
C++学习笔记——输入输出的格式
c++·笔记·学习
j7~2 小时前
【Linux】基础IO超万字解析(文件描述符)(2)
linux·运维·服务器·c++·file·重定向·文件描述
lingzhilab2 小时前
零知派ESP32——TCS3200高精度RGB颜色识别系统教程
c++·mfc