C++软件设计模式之外观(Facade)模式

C++软件设计模式中的外观(Facade)模式

1. 外观模式的定义

外观模式(Facade Pattern)是一种结构型设计模式,它为一个复杂的子系统提供一个简化的接口。外观模式通过一个统一的接口来访问子系统的多个组成部分,使得客户端代码更加简单和易读。

2. 外观模式的主要意图

外观模式的主要意图是为复杂的子系统提供一个简单的接口,减少客户端代码与子系统之间的依赖关系,从而降低系统的复杂度。外观模式通过隐藏子系统的复杂性,使得客户端代码可以更专注于高层次的逻辑,而不需要关心底层实现的细节。

3. 外观模式的主要参与者
  • Facade:提供一个简化的接口,客户端通过这个接口来访问子系统的多个组成部分。
  • Subsystem Classes:复杂子系统的多个组成部分,每个子系统类都有自己的接口和实现。
4. 适用场合

外观模式适用于以下场合:

  • 简化复杂的子系统:当一个子系统包含多个复杂的组件和接口时,可以通过外观模式提供一个简化的接口,隐藏子系统的复杂性。
  • 提供统一的访问点:当需要为一组接口提供一个统一的访问点时,外观模式可以使得客户端代码更加简洁和易读。
  • 降低依赖关系:通过外观模式,客户端代码可以减少对子系统内部组件的直接依赖,从而提高代码的可维护性和可扩展性。
  • 分层系统设计:在分层系统设计中,高层模块可以通过外观模式访问低层模块,而不需要直接与低层模块的多个类打交道。

完整示例代码

假设我们有一个复杂的媒体库系统,包含多个子系统组件,如音频编码器、视频编码器和格式化器。我们可以通过外观模式来提供一个简化的接口,客户端代码可以通过这个接口来访问整个媒体库系统。

1. 子系统类
cpp 复制代码
#include <iostream>
#include <string>

class AudioEncoder {
public:
    void encodeAudio(const std::string& inputFile, const std::string& outputFile) {
        std::cout << "音频编码器: 将音频文件 " << inputFile << " 编码为 " << outputFile << std::endl;
    }
};

class VideoEncoder {
public:
    void encodeVideo(const std::string& inputFile, const std::string& outputFile) {
        std::cout << "视频编码器: 将视频文件 " << inputFile << " 编码为 " << outputFile << std::endl;
    }
};

class FileFormatter {
public:
    void formatFile(const std::string& inputFile, const std::string& outputFile) {
        std::cout << "文件格式化器: 将文件 " << inputFile << " 格式化为 " << outputFile << std::endl;
    }
};

class MediaLibrary {
public:
    void downloadMedia(const std::string& mediaUrl, const std::string& downloadPath) {
        std::cout << "媒体库: 从 " << mediaUrl << " 下载媒体文件到 " << downloadPath << std::endl;
    }
};
2. 外观类
cpp 复制代码
class MediaFacade {
private:
    AudioEncoder _audioEncoder;
    VideoEncoder _videoEncoder;
    FileFormatter _fileFormatter;
    MediaLibrary _mediaLibrary;
public:
    void processMedia(const std::string& mediaUrl, const std::string& outputDir) {
        std::string downloadPath = outputDir + "/downloaded_media.mp4";
        std::string encodedAudioPath = outputDir + "/encoded_audio.mp3";
        std::string encodedVideoPath = outputDir + "/encoded_video.mp4";
        std::string formattedPath = outputDir + "/formatted_media.mp4";

        // 下载媒体文件
        _mediaLibrary.downloadMedia(mediaUrl, downloadPath);

        // 编码音频
        _audioEncoder.encodeAudio(downloadPath, encodedAudioPath);

        // 编码视频
        _videoEncoder.encodeVideo(downloadPath, encodedVideoPath);

        // 格式化文件
        _fileFormatter.formatFile(encodedVideoPath, formattedPath);

        std::cout << "媒体处理完成: " << formattedPath << std::endl;
    }
};
3. 客户端代码
cpp 复制代码
int main() {
    // 创建外观对象
    MediaFacade mediaFacade;

    // 处理媒体文件
    mediaFacade.processMedia("http://example.com/media/file.mp4", "/path/to/output");

    return 0;
}

代码讲解

  1. 子系统类

    • AudioEncoder:负责音频文件的编码。
    • VideoEncoder:负责视频文件的编码。
    • FileFormatter:负责文件的格式化。
    • MediaLibrary:负责从网络下载媒体文件。
  2. 外观类

    • MediaFacade:提供了一个简化的接口 processMedia,用于处理媒体文件。这个方法内部调用了子系统类的多个方法,完成了从下载、编码到格式化的一系列操作。
    • 方法processMedia(const std::string& mediaUrl, const std::string& outputDir) - 接受媒体文件的URL和输出目录,调用子系统的各个组件来完成媒体文件的处理。
  3. 客户端代码

    • 创建 MediaFacade 对象。
    • 调用 processMedia 方法来处理媒体文件,客户端代码只需要关注这个简单的接口,而不需要关心内部的复杂实现。

适用场合的具体示例

  1. 简化复杂的子系统

    • 例如,一个多媒体处理系统可能包含多个子系统,如音频处理、视频处理、文件格式化等。通过外观模式,客户端代码只需要调用一个方法就可以完成多项复杂的处理,而不需要直接调用每个子系统的方法。
  2. 提供统一的访问点

    • 例如,一个网络应用可能需要与多个外部服务进行交互,如数据库、缓存、消息队列等。通过外观模式,可以提供一个统一的接口来管理这些外部服务的调用,使得客户端代码更加简洁。
  3. 降低依赖关系

    • 例如,一个软件系统可能依赖多个库或模块来完成某项任务。通过外观模式,可以隐藏这些库或模块的复杂性,使得客户端代码只需要依赖外观类,而不需要直接依赖每个库或模块。
  4. 分层系统设计

    • 例如,在一个分层的软件架构中,高层次模块可以通过外观模式访问低层次模块,而不需要直接与低层次模块的多个类打交道。

总结

外观模式通过提供一个简化的接口来访问复杂的子系统,减少了客户端代码与子系统之间的依赖关系,使得代码更加简洁和易读。这种模式特别适用于以下场合:

  • 复杂子系统的简化:当子系统包含多个复杂的组件和接口时。
  • 统一的访问点:当需要为一组接口提供一个统一的访问点时。
  • 降低依赖关系:通过外观类隐藏子系统的复杂性,减少客户端代码的依赖。
  • 分层系统设计:在分层的系统设计中,高层模块通过外观类访问低层模块。

Facade 模式的 UML 类图

Facade 模式通过提供一个简化的接口来封装一个复杂的子系统。下面是一个 Facade 模式的 UML 类图示例:

+-----------------+              +-----------------+
|   Client        |              |   Facade        |
|-----------------|              |-----------------|
| - main()         |              | - SubsystemA    |
|                 <------------+>| - SubsystemB    |
|  - processMedia()              || - SubsystemC    |
|                                || - ...           |
|                                |+-----------------+
|                                || - processMedia()|
+-----------------+              +-----------------+
                                    |
                                    v
+-----------------+      +-----------------+      +-----------------+      +-----------------+
|   SubsystemA    |      |   SubsystemB    |      |   SubsystemC    |      |   ...         |
|-----------------|      |-----------------|      |-----------------|      |-----------------|
| - encodeAudio()  |      | - encodeVideo() |      | - formatFile()  |      | - ...           |
+-----------------+      +-----------------+      +-----------------+      +-----------------+

UML 类图解释

  1. Client

    • 职责:客户端类,使用外观类来访问复杂的子系统。
    • 方法
      • main():客户端的主方法,调用外观类的 processMedia() 方法来处理媒体文件。
      • processMedia():客户端通过外观类调用的方法,用于处理媒体文件。
  2. Facade

    • 职责:外观类,提供一个简化的接口来访问子系统的多个组件。
    • 属性
      • SubsystemA:持有子系统A的实例。
      • SubsystemB:持有子系统B的实例。
      • SubsystemC:持有子系统C的实例。
      • ...:可以有更多子系统的实例。
    • 方法
      • processMedia():外观类提供的方法,内部调用子系统的多个方法来完成复杂操作。
  3. SubsystemA

    • 职责:子系统A类,负责某一特定任务(例如音频编码)。
    • 方法
      • encodeAudio():执行音频编码的逻辑。
  4. SubsystemB

    • 职责:子系统B类,负责另一特定任务(例如视频编码)。
    • 方法
      • encodeVideo():执行视频编码的逻辑。
  5. SubsystemC

    • 职责:子系统C类,负责另一特定任务(例如文件格式化)。
    • 方法
      • formatFile():执行文件格式化的逻辑。
  6. 其他子系统

    • 职责:可以有更多的子系统类,每个子系统类都有自己的接口和实现。

详细解释

1. 客户端类(Client)
  • Client 类是使用外观模式的客户端代码。
  • 方法 main()processMedia():客户端通过这些方法调用外观类 FacadeprocessMedia() 方法来处理媒体文件。客户端不需要关心具体的子系统实现细节,只需要使用外观类提供的简化接口。
2. 外观类(Facade)
  • Facade 类是外观模式的核心,它提供了一个简化的接口来访问子系统的多个组件。
  • 属性:外观类持有一个或多个子系统的实例,这些实例可以通过构造函数或setter方法进行初始化。
  • 方法 processMedia():这个方法内部调用子系统的多个方法来完成复杂的操作。例如,处理媒体文件可能需要从网络下载、编码音频、编码视频、格式化文件等步骤,这些步骤都由外观类的 processMedia() 方法统一管理。
3. 子系统类(SubsystemA, SubsystemB, SubsystemC, ...)
  • 子系统类 负责具体的任务,每个子系统类都有自己的接口和实现。
  • 方法:子系统类的方法执行具体的任务,如音频编码、视频编码、文件格式化等。
  • 职责分离:子系统类之间的职责是分离的,每个子系统类都专注于自己的任务。

Facade 模式、Adapter 模式和 Mediator 模式的相似之处和不同之处

1. 相似之处
  • 简化接口

    • Facade 模式Adapter 模式Mediator 模式 都通过提供一个简化的接口来简化复杂系统的使用。
    • 它们的目的都是为了减少客户端代码的复杂度,使得客户端代码更加简洁和易读。
  • 封装细节

    • 这三种模式都通过封装子系统的复杂性来隐藏内部的实现细节。
    • 客户端代码只需要关注高层次的接口,而不需要关心底层的具体实现。
2. 重要不同点
  • Facade 模式

    • 目的:为一个复杂的子系统提供一个简化的接口。
    • 适用场合:当一个子系统包含多个复杂的组件和接口时,通过外观模式提供一个统一的接口来简化客户端的使用。
    • 实现方式:外观类通常拥有多个子系统的实例,并通过组合这些子系统的方法来实现高层次的逻辑。
    • 关系:外观类和子系统类之间的关系是组合(Composition),外观类通过内部持有的子系统类实例来调用子系统的方法。
    • 示例 :媒体处理系统中的外观类 MediaFacade 提供了一个简单的 processMedia 方法来调用多个子系统的方法,完成从下载到格式化的一系列操作。
  • Adapter 模式

    • 目的:将一个类的接口转换成客户端期望的另一个接口。
    • 适用场合:当客户端代码需要与一个已有但接口不兼容的类进行交互时,通过适配器模式来实现接口的转换。
    • 实现方式:适配器类通常通过继承或包含一个已有类来实现接口的转换。
    • 关系:适配器类和被适配的类之间的关系可以是继承(Inheritance)或组合(Composition)。
    • 示例:将一个旧的音频播放器类的接口转换成新的音频播放器接口,使得客户端代码可以无缝地使用新的音频播放器。
    cpp 复制代码
    // 旧的音频播放器接口
    class OldAudioPlayer {
    public:
        void playSound(const std::string& filename) {
            std::cout << "旧音频播放器: 播放 " << filename << std::endl;
        }
    };
    
    // 新的音频播放器接口
    class NewAudioPlayer {
    public:
        virtual void play(const std::string& filename) = 0;
    };
    
    // 适配器类,实现了新的音频播放器接口
    class AudioAdapter : public NewAudioPlayer {
    private:
        OldAudioPlayer _oldPlayer;
    public:
        void play(const std::string& filename) override {
            _oldPlayer.playSound(filename);
        }
    };
    
    // 客户端代码
    int main() {
        std::unique_ptr<NewAudioPlayer> player = std::make_unique<AudioAdapter>();
        player->play("example.mp3");
        return 0;
    }
  • Mediator 模式

    • 目的:通过一个中介者对象来封装多个对象之间的交互,降低对象之间的耦合度。
    • 适用场合:当多个对象之间存在复杂的相互依赖关系时,通过中介者模式来管理这些依赖关系,使得对象之间的交互更加简单和可控。
    • 实现方式:中介者类管理多个对象的交互,每个对象都通过中介者类来通信,而不是直接与其他对象通信。
    • 关系:中介者类和子对象之间的关系是双向的,子对象通过中介者类来通信,中介者类管理子对象之间的交互。
    • 示例:在一个图形用户界面中,多个窗口和按钮之间的交互可以通过一个中介者类来管理。
    cpp 复制代码
    #include <iostream>
    #include <memory>
    #include <vector>
    
    // 中介者接口
    class Mediator {
    public:
        virtual ~Mediator() {}
        virtual void send(const std::string& message, Component* sender) = 0;
    };
    
    // 组件接口
    class Component {
    protected:
        Mediator* _mediator;
    public:
        Component(Mediator* mediator) : _mediator(mediator) {}
        virtual ~Component() {}
        virtual void send(const std::string& message) = 0;
        virtual void receive(const std::string& message) = 0;
    };
    
    // 具体组件A
    class ComponentA : public Component {
    public:
        ComponentA(Mediator* mediator) : Component(mediator) {}
        void send(const std::string& message) override {
            _mediator->send(message, this);
        }
        void receive(const std::string& message) override {
            std::cout << "组件A收到消息: " << message << std::endl;
        }
    };
    
    // 具体组件B
    class ComponentB : public Component {
    public:
        ComponentB(Mediator* mediator) : Component(mediator) {}
        void send(const std::string& message) override {
            _mediator->send(message, this);
        }
    void receive(const std::string& message) override {
            std::cout << "组件B收到消息: " << message << std::endl;
        }
    };
    
    // 具体中介者
    class ConcreteMediator : public Mediator {
    private:
        std::vector<std::unique_ptr<Component>> _components;
    public:
        void addComponent(std::unique_ptr<Component> component) {
            _components.push_back(std::move(component));
        }
    
        void send(const std::string& message, Component* sender) override {
            for (auto& component : _components) {
                if (component.get() != sender) {
                    component->receive(message);
                }
            }
        }
    };
    
    // 客户端代码
    int main() {
        ConcreteMediator mediator;
    
        auto componentA = std::make_unique<ComponentA>(&mediator);
        auto componentB = std::make_unique<ComponentB>(&mediator);
    
        mediator.addComponent(std::move(componentA));
        mediator.addComponent(std::move(componentB));
    
        // 组件A发送消息
        mediator._components[0]->send("Hello, componentB!");
    
        return 0;
    }

重要不同点总结

  • Facade 模式

    • 作用:提供一个简化的接口来访问复杂子系统的多个组件。
    • 关系:外观类与子系统类之间是组合关系。
    • 适用场合:当一个子系统包含多个复杂的组件和接口时,通过外观模式提供一个统一的接口。
  • Adapter 模式

    • 作用:将一个类的接口转换成客户端期望的另一个接口。
    • 关系:适配器类与被适配的类之间可以是继承或组合关系。
    • 适用场合:当客户端代码需要与一个已有但接口不兼容的类进行交互时。
  • Mediator 模式

    • 作用:通过一个中介者对象来封装多个对象之间的交互,降低对象之间的耦合度。
    • 关系:中介者类与子对象之间是双向关系,子对象通过中介者类来通信。
    • 适用场合:当多个对象之间存在复杂的相互依赖关系时,通过中介者模式来管理这些依赖关系。

关键区别

  • Facade 提供一个高层的、简化的接口来访问多个子系统的组件,客户端只需要与外观类交互。
  • Adapter 将一个类的接口转换为客户期望的接口,通常用于适配不同的类或库。
  • Mediator 管理多个对象之间的交互,使得对象之间的依赖关系更加松散,减少了对象之间的直接通信。

Facade 模式在分层软件架构中的作用

1. 分层软件架构简介

分层软件架构通常将一个系统划分为多个层次(或层级),每个层次负责不同的职责。常见的分层结构包括:

  • 表示层(Presentation Layer):与用户交互,处理用户界面逻辑。
  • 业务逻辑层(Business Logic Layer):处理业务逻辑和数据处理。
  • 数据访问层(Data Access Layer):与数据库或其他数据存储进行交互。
  • 外部服务层(External Services Layer):与其他系统或服务进行交互。
2. Facade 模式在分层软件架构中的作用

在分层软件架构中,Facade 模式通常用于提供一个高层次的、简化的接口,使得上层模块可以更方便地访问下层模块。具体作用包括:

  • 简化高层模块的访问:通过外观类,高层模块可以使用一个简单的接口来访问底层模块的多个复杂组件,不需要关注底层的实现细节。
  • 降低耦合度:高层模块与底层模块之间的依赖关系通过外观类来管理,降低了耦合度,方便维护和扩展。
  • 模块化设计:外观类可以作为一个模块的入口点,使得系统的模块化设计更加清晰。
3. 具体示例

假设我们有一个三层架构的电子商务系统,分为表示层、业务逻辑层和数据访问层。

  • 表示层:处理用户界面逻辑,如显示商品列表、购物车等。
  • 业务逻辑层:处理业务逻辑,如订单处理、库存管理等。
  • 数据访问层:与数据库进行交互,获取和存储数据。

我们可以在业务逻辑层中使用 Facade 模式来提供一个简化的接口,使得表示层可以更方便地访问业务逻辑层。

业务逻辑层(子系统)
cpp 复制代码
#include <iostream>
#include <string>

class OrderService {
public:
    void placeOrder(const std::string& userId, const std::string& productId, int quantity) {
        // 订单处理逻辑
        std::cout << "订单服务: 为用户 " << userId << " 下单 " << quantity << " 个 " << productId << std::endl;
    }
};

class InventoryService {
public:
    void checkInventory(const std::string& productId, int quantity) {
        // 库存检查逻辑
        std::cout << "库存服务: 检查 " << productId << " 的库存,数量为 " << quantity << std::endl;
    }
};

class PaymentService {
public:
    void processPayment(const std::string& userId, const std::string& orderId, int amount) {
        // 支付处理逻辑
        std::cout << "支付服务: 为用户 " << userId << " 处理订单 " << orderId << " 的支付,金额为 " << amount << std::endl;
    }
};
业务逻辑层的外观类
cpp 复制代码
class BusinessFacade {
private:
    OrderService _orderService;
    InventoryService _inventoryService;
    PaymentService _paymentService;
public:
    void processPurchase(const std::string& userId, const std::string& productId, int quantity, int amount) {
        // 检查库存
        _inventoryService.checkInventory(productId, quantity);

        // 下单
        std::string orderId = "ORDER123"; // 假设订单ID
        _orderService.placeOrder(userId, productId, quantity);

        // 处理支付
        _paymentService.processPayment(userId, orderId, amount);
    }
};
表示层(客户端代码)
cpp 复制代码
int main() {
    BusinessFacade facade;

    std::string userId = "USER123";
    std::string productId = "PROD456";
    int quantity = 2;
    int amount = 100;

    // 处理购买操作
    facade.processPurchase(userId, productId, quantity, amount);

    return 0;
}

代码解释

  1. 业务逻辑层的子系统类

    • OrderService:负责处理订单逻辑。
    • InventoryService:负责检查库存逻辑。
    • PaymentService:负责处理支付逻辑。
  2. 业务逻辑层的外观类

    • BusinessFacade:提供一个简化的接口 processPurchase,用于处理购买操作。这个方法内部调用了 OrderServiceInventoryServicePaymentService 的多个方法,完成了从检查库存到处理支付的一系列操作。
    • 属性_orderService_inventoryService_paymentService,这些属性是子系统类的实例。
  3. 表示层(客户端代码)

    • 创建 BusinessFacade 对象。
    • 调用 processPurchase 方法来处理购买操作,表示层代码只需要关注这个简单的接口,而不需要关心内部的复杂实现。

Facade 模式在微服务系统中的作用

1. 微服务架构简介

微服务架构将一个应用程序拆分为多个小型、独立的服务,每个服务负责特定的业务功能。这些服务通常通过网络进行通信,可以独立部署和扩展。

2. Facade 模式在微服务系统中的作用

在微服务系统中,Facade 模式可以用于提供一个统一的接口来访问多个微服务,具体作用包括:

  • 简化客户端访问:通过外观类,客户端可以使用一个简单的接口来访问多个微服务,而不需要直接与每个微服务进行通信。
  • 降低耦合度:客户端与微服务之间的依赖关系通过外观类来管理,降低了耦合度,方便维护和扩展。
  • 统一异常处理和日志记录:外观类可以统一处理异常和日志记录,使得客户端代码更加简洁和易读。
3. 具体示例

假设我们有一个微服务系统,包含订单服务、库存服务和支付服务。

订单服务
cpp 复制代码
#include <iostream>
#include <string>

class OrderService {
public:
    std::string placeOrder(const std::string& userId, const std::string& productId, int quantity) {
        // 订单处理逻辑
        std::cout << "订单服务: 为用户 " << userId << " 下单 " << quantity << " 个 " << productId << std::endl;
        return "ORDER123"; // 假设订单ID
    }
};
库存服务
cpp 复制代码
class InventoryService {
public:
    bool checkInventory(const std::string& productId, int quantity) {
        // 库存检查逻辑
        std::cout << "库存服务: 检查 " << productId << " 的库存,数量为 " << quantity << std::endl;
        return true; // 假设库存充足
    }
};
支付服务
cpp 复制代码
class PaymentService {
public:
    void processPayment(const std::string& userId, const std::string& orderId, int amount) {
        // 支付处理逻辑
        std::cout << "支付服务: 为用户 " << userId << " 处理订单 " << orderId << " 的支付,金额为 " << amount << std::endl;
    }
};
微服务系统的外观类
cpp 复制代码
class MicroserviceFacade {
private:
    std::unique_ptr<OrderService> _orderService;
    std::unique_ptr<InventoryService> _inventoryService;
    std::unique_ptr<PaymentService> _paymentService;
public:
    MicroserviceFacade() : _orderService(std::make_unique<OrderService>()), _inventoryService(std::make_unique<InventoryService>()), _paymentService(std::make_unique<PaymentService>()) {}

    void processPurchase(const std::string& userId, const std::string& productId, int quantity, int amount) {
        // 检查库存
        if (!_inventoryService->checkInventory(productId, quantity)) {
            std::cout << "库存不足,无法完成购买" << std::endl;
            return;
        }

        // 下单
        std::string orderId = _orderService->placeOrder(userId, productId, quantity);

        // 处理支付
        _paymentService->processPayment(userId, orderId, amount);

        std::cout << "购买操作完成: " << orderId << std::endl;
    }
};
客户端代码
cpp 复制代码
int main() {
    MicroserviceFacade facade;

    std::string userId = "USER123";
    std::string productId = "PROD456";
    int quantity = 2;
    int amount = 100;

    // 处理购买操作
    facade.processPurchase(userId, productId, quantity, amount);

    return 0;
}

代码解释

  1. 微服务类

    • OrderService:负责处理订单逻辑,返回订单ID。
    • InventoryService:负责检查库存逻辑,返回库存是否充足。
    • PaymentService:负责处理支付逻辑。
  2. 微服务系统的外观类

    • MicroserviceFacade:提供一个简化的接口 processPurchase,用于处理购买操作。这个方法内部调用了 OrderServiceInventoryServicePaymentService 的多个方法,完成了从检查库存到处理支付的一系列操作。
    • 属性_orderService_inventoryService_paymentService,这些属性是微服务类的实例。
    • 方法processPurchase - 接受用户ID、产品ID、数量和金额,调用微服务的各个组件来完成购买操作。
  3. 客户端代码

    • 创建 MicroserviceFacade 对象。
    • 调用 processPurchase 方法来处理购买操作,客户端代码只需要关注这个简单的接口,而不需要关心内部的复杂实现。

总结

  • 分层软件架构中的 Facade 模式

    • 作用:提供一个高层次的、简化的接口,使得上层模块可以更方便地访问下层模块。
    • 优点:简化高层模块的访问,降低耦合度,模块化设计更加清晰。
  • 微服务系统中的 Facade 模式

    • 作用:提供一个统一的接口来访问多个微服务,简化客户端的访问逻辑。
    • 优点:简化客户端访问,降低耦合度,统一异常处理和日志记录。

通过 Facade 模式,无论是分层软件架构还是微服务系统,都可以有效地隐藏复杂性,提供更简洁和易用的接口,从而提高系统的可维护性和可扩展性。希望这些解释能帮助你更好地理解 Facade 模式在不同场景中的应用。

相关推荐
lqqjuly2 小时前
特殊的“Undefined Reference xxx“编译错误
c语言·c++
冰红茶兑滴水3 小时前
云备份项目--工具类编写
linux·c++
刘好念3 小时前
[OpenGL]使用 Compute Shader 实现矩阵点乘
c++·计算机图形学·opengl·glsl
酒鬼猿4 小时前
C++进阶(二)--面向对象--继承
java·开发语言·c++
姚先生974 小时前
LeetCode 209. 长度最小的子数组 (C++实现)
c++·算法·leetcode
小王爱吃月亮糖5 小时前
QT开发【常用控件1】-Layouts & Spacers
开发语言·前端·c++·qt·visual studio
aworkholic5 小时前
opencv sdk for java中提示无stiching模块接口的问题
java·c++·opencv·jni·opencv4android·stiching
程序员老冯头5 小时前
第十六章 C++ 字符串
开发语言·c++
Xenia2235 小时前
复习篇~第二章程序设计基础
c++·算法
想睡觉 . 我也想睡觉 .5 小时前
【C++算法】1.【模板】前缀和
开发语言·c++·算法