设计模式:代理模式

代理模式是很常见的设计模式,即使没有专门学习过这种设计模式,在工作中也一定用过这种设计模式。在实际生活中,代理模式也是常见的,比如内阁首辅相对于皇帝,前者是后者的代理,内阁首辅收到奏折时,往往也要做一些预处理和后处理。

当我们需要给原始类增加一些功能、日志、性能监控时,通过修改原始类当然是可以实现的,但是这样就侵入了原来的逻辑,违背了开闭原则。并且新增的功能与原有的功能本来就属于不同范畴的功能。

在不修改原始类的基础上,增加新的功能,就需要用到代理模式。有些类也是无法修改的,这种情况下,只能使用代理模式。

在平时的开发中,为了代码使用方便,我们往往会对一些原始的接口进行封装。在原始接口的基础上增加一些功能或者日志。这样我们在使用对应功能的时候,就可以直接使用我们封装的接口,而不是原始接口,这就是代理模式。

如下是在std::thread的基础上封装的Thread类,通过该类可以设置线程的名字。为了在创建线程的时候指定线程的名字,封装了Thread类,Thread可以看作std::thread的代理类。

cpp 复制代码
#include <iostream>
#include <thread>
#include <unistd.h>

class Thread {
  public:
   template <class Function, class... Args>
   Thread(std::string const& name, Function&& f, Args&&... args) noexcept
       : internal_(std::forward<Function>(f), std::forward<Args>(args)...) {
     set_name(name);
   }

   virtual ~Thread() noexcept {
     if (internal_.joinable()) {
       internal_.join();
     }
   }


   bool joinable() const noexcept { return internal_.joinable(); }

   void join() {
     if (joinable()) {
       internal_.join();
     }
   }

   std::thread::native_handle_type native_handle() noexcept { return internal_.native_handle(); }

  private:
   void set_name(std::string const& name) noexcept {
     if (!name.empty()) {
       uint64_t const thread_name_max{15};

       if (name.length() > thread_name_max) {
         pthread_setname_np(native_handle(), name.substr(0, thread_name_max).c_str());

       } else {
         pthread_setname_np(native_handle(), name.c_str());
       }
     }
   }

  private:
   std::thread internal_;
 };


int main() {
  Thread t("testthread", [](){
                std::cout << "thread enter\n";
                sleep(10);
                std::cout << "thread exit\n";
                });

  t.join();
  return 0;
}

1静态代理

静态代理,就是针对一个原始类,实现一个代理类,这个代理类只能对这一个原始类起到代理的作用。如下代码,是代理模式的典型使用方式,代理类与原始类实现相同的接口,代理类中有一个属性是原始类。

cpp 复制代码
#include <iostream>

// 接口
class Subject {
public:
    virtual void Request() const = 0;
    virtual ~Subject() = default;
};

// 原始类
class RealSubject : public Subject {
public:
    void Request() const override {
        std::cout << "RealSubject: 处理请求" << std::endl;
    }
};

// 代理类
class Proxy : public Subject {
private:
    RealSubject* real_subject_;

public:
    Proxy() : real_subject_(new RealSubject()) {}

    ~Proxy() {
        delete real_subject_;
    }

    void Request() const override {
        std::cout << "Proxy: 预处理请求" << std::endl;

        real_subject_->Request();

        std::cout << "Proxy: 后续处理" << std::endl;
    }
};

int main() {
    Proxy proxy;
    proxy.Request();
    return 0;
}

2动态代理

使用静态代理,如果原始类很多的话,那么针对每一个原始类,都要实现一个代理类,这样会造成类的数量成倍的增加。为了解决这个问题,出现了动态代理。

如下代码,是动态代理的例子,动态代理类是一个类模板,该代理类代理的是那个类通过模板参数指定。原始类、预处理函数、后处理函数,均通过构造函数的的参数进行传递。

cpp 复制代码
#include <iostream>
#include <functional>
#include <memory>

// 抽象类
class IComponent {
public:
    virtual void Operation() = 0;
    virtual ~IComponent() = default;
};

// 原始类
class ConcreteComponent : public IComponent {
public:
    void Operation() override {
        std::cout << "ConcreteComponent: 核心操作" << std::endl;
    }
};

// 代理类
template <typename T>
class DynamicProxy : public IComponent {
private:
    std::unique_ptr<T> target_;
    std::function<void()> pre_handler_;
    std::function<void()> post_handler_;

public:
    DynamicProxy(std::unique_ptr<T> target,
                std::function<void()> pre,
                std::function<void()> post)
        : target_(std::move(target)),
          pre_handler_(pre),
          post_handler_(post) {}

    void Operation() override {
        // 前置处理
        if (pre_handler_) pre_handler_();

        // 委托调用
        target_->Operation();

        // 后置处理
        if (post_handler_) post_handler_();
    }
};

int main() {
    // 创建动态代理(可运行时配置)
    auto proxy = std::make_unique<DynamicProxy<ConcreteComponent>>(
        std::make_unique<ConcreteComponent>(),
        []() { std::cout << "DynamicProxy: 预处理" << std::endl; },
        []() { std::cout << "DynamicProxy: 后续处理" << std::endl; }
    );

    proxy->Operation();
    return 0;
}
相关推荐
yangyang_z5 小时前
【C++设计模式之Template Method Pattern】
设计模式
源远流长jerry7 小时前
常用设计模式
设计模式
z26373056117 小时前
六大设计模式--OCP(开闭原则):构建可扩展软件的基石
设计模式·开闭原则
01空间13 小时前
设计模式简述(十八)享元模式
设计模式·享元模式
秋名RG16 小时前
深入理解设计模式之原型模式(Prototype Pattern)
设计模式·原型模式
Yang三少喜欢撸铁19 小时前
【阿里云免费领取域名以及ssl证书,通过Nginx反向代理web服务】
nginx·阿里云·代理模式·ssl
Li小李同学Li1 天前
设计模式【cpp实现版本】
单例模式·设计模式
Blurpath1 天前
什么是静态住宅IP?为什么静态住宅IP能提高注册通过率?
网络·代理模式·ip代理·住宅ip
周努力.1 天前
设计模式之状态模式
设计模式·状态模式
python算法(魔法师版)2 天前
JavaScript性能优化实战,从理论到落地的全面指南
开发语言·性能优化·前端框架·代理模式