当前位置: 首页 > article >正文

外观设计模式学习

1.介绍

外观模式(Facade Pattern) 是一种结构型设计模式,通过提供一个统一的接口,用于访问子系统中的一组接口,从而简化客户端与复杂系统之间的交互。它隐藏了系统的复杂性,使得客户端只需与一个简单的接口交互,而无需了解内部的实现细节。

核心思想

  • 简化接口:外观模式通过创建一个高级接口,屏蔽了子系统的复杂性。
  • 解耦:客户端无需直接与子系统的复杂接口交互,减少了系统之间的依赖性。

模式结构

  1. Facade(外观类):提供一个统一的接口,用来访问子系统中的功能。
  2. Subsystem(子系统):实现子系统的实际功能,对外隐藏其内部细节。
  3. Client(客户端):通过外观类与子系统交互。

外观模式的缺点

  1. 可能过多依赖:如果外观类变得过于复杂,可能会导致其自身成为一个“大而全”的类。
  2. 隐藏细节:外观模式可能会掩盖子系统的一些细节,从而限制了灵活性。

2.示例

假设我们要实现一个家庭影院系统,它包含多个子系统,如电视、音响、播放器等。客户端希望通过一个统一的接口来控制整个系统。

#include <iostream>
#include <string>

// 子系统1:电视
class Television {
public:
    void turnOn() { std::cout << "Television is ON\n"; }
    void turnOff() { std::cout << "Television is OFF\n"; }
};

// 子系统2:音响
class SoundSystem {
public:
    void turnOn() { std::cout << "SoundSystem is ON\n"; }
    void turnOff() { std::cout << "SoundSystem is OFF\n"; }
    void setVolume(int level) { std::cout << "SoundSystem volume set to " << level << "\n"; }
};

// 子系统3:播放器
class MediaPlayer {
public:
    void play(const std::string& movie) { std::cout << "Playing movie: " << movie << "\n"; }
    void stop() { std::cout << "Stopping the movie\n"; }
};

// 外观类
class HomeTheaterFacade {
private:
    Television tv; // 包含了其他类对象
    SoundSystem soundSystem;
    MediaPlayer mediaPlayer;

public:
    void watchMovie(const std::string& movie) {
        std::cout << "Get ready to watch a movie...\n";
        tv.turnOn();
        soundSystem.turnOn();
        soundSystem.setVolume(50);
        mediaPlayer.play(movie);
    }
    
    // 直接调用其他接口类
    void endMovie() {
        std::cout << "Shutting down the home theater...\n";
        mediaPlayer.stop();
        soundSystem.turnOff();
        tv.turnOff();
    }
};

// 客户端代码
int main() {
    HomeTheaterFacade homeTheater;

    homeTheater.watchMovie("Inception");
    homeTheater.endMovie();

    return 0;
}

3.抽象外观类

当增加或移除子系统时需要修改外观类,这违背了“开闭原则”。将外观类与具体的子系统解耦,通过依赖注入动态管理子系统。这种方式可以在运行时动态增加或移除子系统,而无需修改外观类的代码。

#include <iostream>
#include <memory>
#include <unordered_map>
#include <string>

// 子系统接口
class Subsystem {
public:
    virtual void execute() = 0;
    virtual ~Subsystem() = default;
};

// 具体子系统1
class SubsystemA : public Subsystem {
public:
    void execute() override { std::cout << "SubsystemA executed.\n"; }
};

// 具体子系统2
class SubsystemB : public Subsystem {
public:
    void execute() override { std::cout << "SubsystemB executed.\n"; }
};

// 外观类
class Facade {
private:
    // 依赖抽象的子系统类
    std::unordered_map<std::string, std::shared_ptr<Subsystem>> subsystems;

public:
    void addSubsystem(const std::string& name, std::shared_ptr<Subsystem> subsystem) {
        subsystems[name] = subsystem;
    }

    void removeSubsystem(const std::string& name) {
        subsystems.erase(name);
    }

    void executeSubsystem(const std::string& name) {
        if (subsystems.count(name)) {
            subsystems[name]->execute();
        } else {
            std::cout << "Subsystem " << name << " not found.\n";
        }
    }
};

// 客户端代码
int main() {
    Facade facade;

    // 动态添加子系统
    facade.addSubsystem("A", std::make_shared<SubsystemA>());
    facade.addSubsystem("B", std::make_shared<SubsystemB>());

    // 调用子系统
    facade.executeSubsystem("A");
    facade.executeSubsystem("B");

    // 动态移除子系统
    facade.removeSubsystem("A");
    facade.executeSubsystem("A");

    return 0;
}


http://www.kler.cn/a/500990.html

相关文章:

  • HTML5实现好看的端午节网页源码
  • 【C++】深入理解字符串操作:pop_back()方法详解
  • 抖音生活服务举办直营服务商年度峰会 服务商支付交易额同比涨85%
  • 【C语言系列】函数递归
  • 面试:C++类成员初始化顺序
  • SpringCloud系列教程:微服务的未来(十)服务调用、注册中心原理、Nacos注册中心
  • HTTP 请求与响应的结构
  • 《CPython Internals》阅读笔记:p96-p96
  • 矩阵碰一碰发视频的视频剪辑功能源码搭建,支持OEM
  • 采用pycorrector纠错word文件段落,并保存为word文件标红显示出来
  • 消息中间件-kafka工作原理和配置
  • FreePBX 17 on ubuntu24 with Asterisk 20
  • 【Spring】@Size 无法拦截null的原因
  • Julia语言的软件工程
  • .NET Core NPOI 导出图片到Excel指定单元格并自适应宽度
  • Cesium加载地形
  • STM32 : 波特率发生器
  • ceph 数据均衡
  • K11082 加密与解密
  • Vue2+OpenLayers使用Overlay实现点击获取当前经纬度信息(提供Gitee源码)