设计模式:代理模式

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

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

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

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

如下是在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;
}
相关推荐
付聪12105 小时前
装饰器模式
设计模式
扣丁梦想家5 小时前
设计模式教程:外观模式(Facade Pattern)
设计模式·外观模式
強云5 小时前
23种设计模式 - 装饰器模式
c++·设计模式·装饰器模式
強云5 小时前
23种设计模式 - 外观模式
设计模式·外观模式
鄃鳕6 小时前
单例模式【C++设计模式】
c++·单例模式·设计模式
DanceDonkey8 小时前
多层代理模式解析Invocation
代理模式
allnlei8 小时前
懒加载代理模式(Lazy Initialization Proxy Pattern)
代理模式
扣丁梦想家9 小时前
设计模式教程:命令模式(Command Pattern)
设计模式·命令模式
強云10 小时前
23种设计模式 - 迭代器模式
设计模式·迭代器模式
小王子102410 小时前
设计模式Python版 迭代器模式
python·设计模式·迭代器模式