17370845950

c++如何实现一个代理模式_c++结构型设计模式Proxy【详解】
代理模式核心是通过代理类控制对真实对象的访问,不改变原接口即可添加权限校验、日志等逻辑;其结构含抽象接口、真实对象和代理对象三部分,代理持真实对象引用并转发调用。

代理模式在C++中核心是用一个代理类(Proxy)控制对真实对象(RealSubject)的访问,既不改变原接口,又能添加权限校验、延迟加载、日志记录等额外逻辑。

一、代理模式的基本结构

需要三部分协同工作:

  • 抽象接口(Subject):定义业务方法,供 Proxy 和 RealSubject 共同实现;
  • 真实对象(RealSubject):真正执行业务逻辑的类;
  • 代理对象(Proxy):持有一个 RealSubject 指针/引用,转发调用,并在前后插入控制逻辑。

二、经典静态代理实现(以文件读取为例)

假设我们想对文件读取操作加访问日志和权限检查:

class FileReader {
public:
    virtual ~FileReader() = default;
    virtual std::string read(const std::string& path) = 0;
};

class RealFileReader : public FileReader {
public:
    std::string read(const std::string& path) override {
        return "Content from " + path; // 真实读取逻辑
    }
};

class LoggingProxy : public FileReader {
private:
    std::unique_ptr real_reader;
public:
    LoggingProxy() : real_reader(std::make_unique()) {}

    std::string read(const std::string& path) override {
        std::cout << "[LOG] Accessing file: " << path << std::endl;
        // 可在此加权限判断:if (!hasPermission(path)) throw std::runtime_error("No access");
        return real_reader->read(path);
    }
};

使用时只需面向 FileReader 接口编程:

std::unique_ptr proxy = std::make_unique();
std::cout << proxy->read("config.txt") << std::endl;

三、智能指针+模板代理(支持任意类型)

若不想为每个类手写代理,可用模板封装通用代理壳:

template
class GenericProxy {
private:
    std::unique_ptr target;
public:
    explicit GenericProxy(std::unique_ptr t) : target(std::move(t)) {}

    template
    auto operator->() -> decltype(target.get()) {
        std::cout << "[Proxy] Forwarding call...\n";
        return target.get();
    }

    // 若需重载具体方法,可显式转发(推荐用于关键接口)
    template
    auto read(Args&&... args) -> decltype(std::declval().read(std::forward(args)...)) {
        std::cout << "[Proxy] Before read\n";
        auto result = target->read(std::forward(args)...);
        std::cout << "[Proxy] After read\n";
        return result;
    }
};

注意:这种泛型方式适合轻量包装,但无法完全替代接口抽象——强类型安全和开闭原则仍依赖基类接口。

四、常见变体与使用场景

远程代理(Remote Proxy):把本地调用转为网络请求(如 gRPC stub);
虚代理(Virtual Proxy):延迟初始化重量级对象(如大图加载器,首次调用才 new);
保护代理(Protection Proxy):运行时检查用户角色(如 admin-only 方法);
智能引用(Smart Reference):自动计数、释放或锁定(类似 std::shared_ptr 的附加语义)。

基本上就这些。代理模式不复杂但容易忽略接口抽象的重要性——没有统一 Subject,Proxy 就失去替换性和扩展性。