【C++】建造者与代理模式实战解析

文章目录

      • [建造者模式 & 代理模式(C++ 详解)](#建造者模式 & 代理模式(C++ 详解))
    • [一、建造者模式(Builder Pattern)](#一、建造者模式(Builder Pattern))
    • [二、代理模式(Proxy Pattern)](#二、代理模式(Proxy Pattern))
      • [1. 核心概念](#1. 核心概念)
      • [2. C++ 代码示例(保护代理 + 日志代理)](#2. C++ 代码示例(保护代理 + 日志代理))
      • [3. 输出结果](#3. 输出结果)
      • [4. 应用场景](#4. 应用场景)
      • 总结
        • [1. 建造者模式](#1. 建造者模式)
        • [2. 代理模式](#2. 代理模式)
        • [3. 核心区别](#3. 核心区别)

建造者模式 & 代理模式(C++ 详解)

建造者模式和代理模式都属于设计模式的核心范畴,但解决的问题完全不同:

  • 建造者模式 :聚焦复杂对象的分步创建,将"对象构建"与"对象表示"解耦;
  • 代理模式 :聚焦对象访问控制,为目标对象提供一个代理,控制对它的访问(如权限、延迟加载、日志等)。

下面分别讲解两种模式的核心思想、结构、代码示例和应用场景。


一、建造者模式(Builder Pattern)

1. 核心概念

(1)解决的问题

当一个对象的创建需要多个步骤多个部件,且不同组合会生成不同"表示"时(比如:创建一个电脑,需要选CPU、内存、硬盘、显卡,不同配置组合出游戏本/办公本/服务器),直接在构造函数中创建会导致代码臃肿、可读性差,建造者模式将"分步构建"和"最终组装"分离。

(2)核心结构
角色 作用
产品(Product) 最终要创建的复杂对象(如电脑)
抽象建造者(Builder) 定义构建产品的所有步骤接口(如setCPU、setMemory、setDisk等)
具体建造者(ConcreteBuilder) 实现抽象建造者的接口,完成具体部件的构建(如游戏本建造者、办公本建造者)
指挥者(Director) 控制构建流程(如"先装CPU→再装内存→再装硬盘"),调用建造者的步骤完成构建
(3)核心优势
  • 分步构建复杂对象,代码清晰;
  • 不同建造者可生成不同配置的产品,扩展灵活;
  • 指挥者与建造者解耦,修改构建流程只需改指挥者。

2. C++ 代码示例(构建电脑)

cpp 复制代码
#include <iostream>
#include <string>

// 1. 产品:电脑(复杂对象)
class Computer {
private:
    std::string cpu;    // CPU
    std::string memory; // 内存
    std::string disk;   // 硬盘
    std::string gpu;    // 显卡
public:
    // 设置部件
    void setCPU(const std::string& cpu) { this->cpu = cpu; }
    void setMemory(const std::string& memory) { this->memory = memory; }
    void setDisk(const std::string& disk) { this->disk = disk; }
    void setGPU(const std::string& gpu) { this->gpu = gpu; }
    
    // 展示配置
    void showConfig() const {
        std::cout << "电脑配置:" << std::endl;
        std::cout << "CPU: " << cpu << std::endl;
        std::cout << "内存: " << memory << std::endl;
        std::cout << "硬盘: " << disk << std::endl;
        std::cout << "显卡: " << gpu << std::endl;
    }
};

// 2. 抽象建造者:定义构建电脑的所有步骤
class ComputerBuilder {
protected:
    Computer* computer; // 持有产品对象
public:
    ComputerBuilder() { computer = new Computer(); }
    virtual ~ComputerBuilder() { delete computer; }
    
    // 纯虚函数:构建各个部件(子类必须实现)
    virtual void buildCPU() = 0;
    virtual void buildMemory() = 0;
    virtual void buildDisk() = 0;
    virtual void buildGPU() = 0;
    
    // 返回构建好的产品
    Computer* getComputer() { return computer; }
};

// 3. 具体建造者1:游戏本建造者(高性能配置)
class GameComputerBuilder : public ComputerBuilder {
public:
    void buildCPU() override { computer->setCPU("Intel i9-14900K"); }
    void buildMemory() override { computer->setMemory("32GB DDR5 6400"); }
    void buildDisk() override { computer->setDisk("2TB NVMe 4.0"); }
    void buildGPU() override { computer->setGPU("NVIDIA RTX 4090"); }
};

// 4. 具体建造者2:办公本建造者(低功耗、轻便配置)
class OfficeComputerBuilder : public ComputerBuilder {
public:
    void buildCPU() override { computer->setCPU("Intel i5-1340P"); }
    void buildMemory() override { computer->setMemory("16GB DDR4 3200"); }
    void buildDisk() override { computer->setDisk("1TB NVMe 3.0"); }
    void buildGPU() override { computer->setGPU("Intel UHD Graphics"); }
};

// 5. 指挥者:控制构建流程(固定步骤,无需关心具体配置)
class Director {
public:
    // 指挥构建流程:CPU → 内存 → 硬盘 → 显卡
    Computer* construct(ComputerBuilder* builder) {
        builder->buildCPU();
        builder->buildMemory();
        builder->buildDisk();
        builder->buildGPU();
        return builder->getComputer();
    }
};

// 客户端调用
int main() {
    // 1. 创建指挥者
    Director director;
    
    // 2. 构建游戏本
    ComputerBuilder* gameBuilder = new GameComputerBuilder();
    Computer* gameComputer = director.construct(gameBuilder);
    std::cout << "=== 游戏本配置 ===" << std::endl;
    gameComputer->showConfig();
    
    // 3. 构建办公本
    ComputerBuilder* officeBuilder = new OfficeComputerBuilder();
    Computer* officeComputer = director.construct(officeBuilder);
    std::cout << "\n=== 办公本配置 ===" << std::endl;
    officeComputer->showConfig();
    
    // 释放资源
    delete gameBuilder;   // 内部会删除computer
    delete officeBuilder;
    return 0;
}

3. 输出结果

复制代码
=== 游戏本配置 ===
电脑配置:
CPU: Intel i9-14900K
内存: 32GB DDR5 6400
硬盘: 2TB NVMe 4.0
显卡: NVIDIA RTX 4090

=== 办公本配置 ===
电脑配置:
CPU: Intel i5-1340P
内存: 16GB DDR4 3200
硬盘: 1TB NVMe 3.0
显卡: Intel UHD Graphics

4. 应用场景

  • 复杂对象的创建(如:汽车、电脑、文档、报表);
  • 对象创建需要多个步骤,且步骤顺序固定/可调整;
  • 需生成不同配置的同一类产品(如:不同配置的手机、不同风格的蛋糕)。

二、代理模式(Proxy Pattern)

1. 核心概念

(1)解决的问题

为目标对象提供一个"代理",控制对目标对象的访问,代理可以在访问目标对象前后添加额外逻辑(如:权限校验、日志记录、延迟加载、远程调用),而客户端无需感知目标对象的存在。

(2)核心结构
角色 作用
抽象主题(Subject) 定义目标对象和代理对象的共同接口(保证代理和目标对象可替换)
真实主题(RealSubject) 实际执行业务逻辑的目标对象
代理(Proxy) 实现抽象主题接口,持有真实主题的引用,控制对真实主题的访问
(3)常见类型
  • 静态代理:编译期确定代理类(如下方示例);
  • 动态代理:运行时生成代理类(C++ 需手动实现,Java 有 JDK 动态代理/CGLIB);
  • 按功能分类:远程代理(访问远程对象)、虚拟代理(延迟加载)、保护代理(权限控制)、日志代理(记录访问日志)。

2. C++ 代码示例(保护代理 + 日志代理)

场景:模拟"文件下载",代理先校验用户权限,再记录下载日志,最后调用真实下载逻辑。

cpp 复制代码
#include <iostream>
#include <string>

// 1. 抽象主题:下载接口
class Downloader {
public:
    virtual ~Downloader() = default;
    virtual void download(const std::string& url, const std::string& user) = 0;
};

// 2. 真实主题:真实的下载器(核心业务逻辑)
class RealDownloader : public Downloader {
public:
    void download(const std::string& url, const std::string& user) override {
        // 真实的下载逻辑
        std::cout << "[真实下载] 用户" << user << "下载文件:" << url << std::endl;
    }
};

// 3. 代理:下载代理(权限校验 + 日志记录)
class DownloadProxy : public Downloader {
private:
    RealDownloader* realDownloader; // 持有真实主题的引用
    
    // 额外逻辑1:权限校验
    bool checkPermission(const std::string& user) {
        std::cout << "[权限校验] 检查用户" << user << "的下载权限..." << std::endl;
        // 模拟:只有admin和user1有权限
        return (user == "admin" || user == "user1");
    }
    
    // 额外逻辑2:记录日志
    void logDownload(const std::string& url, const std::string& user) {
        std::cout << "[日志记录] 用户" << user << "下载了" << url << ",时间:2026-03-17" << std::endl;
    }
public:
    DownloadProxy() {
        realDownloader = new RealDownloader(); // 创建真实主题
    }
    
    ~DownloadProxy() {
        delete realDownloader;
    }
    
    // 代理的核心方法:控制访问
    void download(const std::string& url, const std::string& user) override {
        // 步骤1:权限校验
        if (!checkPermission(user)) {
            std::cout << "[权限拒绝] 用户" << user << "无下载权限!" << std::endl;
            return;
        }
        
        // 步骤2:调用真实下载逻辑
        realDownloader->download(url, user);
        
        // 步骤3:记录日志
        logDownload(url, user);
    }
};

// 客户端调用
int main() {
    // 客户端只和代理交互,无需知道真实下载器的存在
    Downloader* downloader = new DownloadProxy();
    
    // 测试1:有权限的用户
    std::cout << "=== 测试1:admin下载 ===" << std::endl;
    downloader->download("https://example.com/file.zip", "admin");
    
    // 测试2:无权限的用户
    std::cout << "\n=== 测试2:guest下载 ===" << std::endl;
    downloader->download("https://example.com/file.zip", "guest");
    
    // 释放资源
    delete downloader;
    return 0;
}

3. 输出结果

复制代码
=== 测试1:admin下载 ===
[权限校验] 检查用户admin的下载权限...
[真实下载] 用户admin下载文件:https://example.com/file.zip
[日志记录] 用户admin下载了https://example.com/file.zip,时间:2026-03-17

=== 测试2:guest下载 ===
[权限校验] 检查用户guest的下载权限...
[权限拒绝] 用户guest无下载权限!

4. 应用场景

  • 权限控制:如接口访问权限、文件操作权限;
  • 日志/监控:记录接口调用的入参、出参、耗时;
  • 延迟加载:对象创建成本高时,代理先不创建,直到真正使用时再初始化;
  • 远程代理:访问远程服务器的对象(如 RPC 框架的代理);
  • 缓存代理:缓存频繁访问的结果,避免重复计算/请求。

总结

1. 建造者模式
  • 核心:分步构建复杂对象,将"构建步骤"与"产品配置"分离;
  • 关键:指挥者控制流程,建造者实现具体部件,产品是最终结果;
  • 适用:复杂对象、多步骤创建、多配置变体的场景。
2. 代理模式
  • 核心:控制目标对象的访问,在访问前后添加额外逻辑;
  • 关键:代理和目标对象实现同一接口,客户端无感知;
  • 适用:权限控制、日志、延迟加载、远程调用等需"增强访问逻辑"的场景。
3. 核心区别
维度 建造者模式 代理模式
解决的问题 复杂对象的分步创建 目标对象的访问控制
核心关系 指挥者 → 建造者 → 产品 客户端 → 代理 → 真实对象
核心目的 生成不同配置的对象 增强/控制对象的访问逻辑
相关推荐
2501_945424802 小时前
C++跨平台开发实战
开发语言·c++·算法
John_ToDebug2 小时前
死锁案例:UI 线程阻塞等待跨进程 COM 注入
c++·windows·笔记
煤球王子2 小时前
学而时习之:C++中的预处理
c++
AsDuang2 小时前
Python 3.12 MagicMethods - 54 - __rrshift__
开发语言·python
Bert.Cai2 小时前
Python字符串详解
开发语言·python
码界奇点2 小时前
基于模块化架构的Unity游戏开发框架设计与实现
java·c++·unity·架构·毕业设计·源代码管理
爱滑雪的码农2 小时前
Java基础五:运算符与循环结构
java·开发语言
于先生吖2 小时前
基于 Java 开发智慧社区系统:跑腿 + 家政 + 本地生活服务实战教程
java·开发语言·生活