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();
    }
};

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

相关推荐
梅头脑12 小时前
学了6种设计模式却写出了同事看不懂的代码——SOLID五原则反例对照,治好了我的"过度设计"
设计模式
呜喵王阿尔萨斯12 小时前
extern “C“ in C++
c语言·c++·算法
乐观勇敢坚强的老彭12 小时前
C++信奥静态数组和动态数组
数据结构·c++·算法
gumichef13 小时前
第一章:面向对象核心——类和对象深度讲解
开发语言·c++
ao-weilai13 小时前
C++基础:类和对象
开发语言·c++
郝学胜-神的一滴13 小时前
[简化版 GAMES 104] 现代游戏引擎 04:从0到1构建你的游戏世界
c++·游戏·unity·游戏引擎·软件工程·unreal engine
Bryce学亮13 小时前
FileLine,基于 Qt 6 + QML 构建的跨平台文件传输与即时通讯工具
数据库·c++·人工智能·python·qt·github
旖旎夜光13 小时前
LeetCode 991: 坏了的计算器(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
旖旎夜光14 小时前
LeetCode 553:最优除法(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
workflower14 小时前
案例:大模型驱动的“发现- 研判- 整改- 验证”全闭环治理体系
人工智能·深度学习·机器学习·设计模式·机器人