模式简介
代理模式最熟悉的应用就是“科学上网”了。比如我们想要访问“油管”(YG),但是很不幸,在国内有“长城”(W),我们是没有权限访问油管的IP(YIP)的。那么换一个代理的思路,虽然我们不能直接访YIP,但是我们可以访问其他没有被封锁IP的服务器,比如自己搭建一个服务器SIP。这样,我们先把请求发送给国外的SIP(肯定是加密访问的),之后SIP再把我们的请求转发给YIP,YIP不知道SIP是我们的代理,YIP会正常回复SIP所有合理的请求。之后SIP再把获得的YIP的数据发给我们。但是,本地浏览器客户端上不需要改变任何的功能,所有调用的方法没有发生改变,唯一的区别是请求的IP可能成为了SIP了,而不是YIP。
通过使用SIP,绕过W访问YG的过程,就称为一个代理的过程。这里面,SIP扮演了代理的角色。通过上面的例子,可以总结出代理的一般形式:
- 代理提供了一个统一的客户端访问接口。上述例子中,我们的浏览器功能方法不需要任何改动,只是改了下访问的IP
- 代理本身处理的是客户的请求,并把这个请求交给实际的处理方,之后在把处理方的结果返回给客户。它相当于一个中间者,但是很多情况下,请求和处理请求的双方是感知不到代理的存在的。RPC机制就类似于这个过程。
- 代理可以起到隔离的作用。有些时候,为了安全等机制,我们无法直接访问服务器,但是服务器提供了代理类的接口,我们可以通过代理进行访问。
模式实现
#include <iostream>
#include <memory>
class Subject { // 统一的对象接口
public:
virtual void request() = 0;
};
class RealSubject : public Subject { // 具体对象
public:
void request() override {
std::cout << "do proxy request...\n";
}
};
class Proxy : public Subject { // 代理
public:
Proxy(std::shared_ptr<Subject> subject) {
m_spSubject = std::move(subject);
}
void request() override {
preRequest();
m_spSubject->request();
postRequest();
}
protected:
void preRequest() {
std::cout << "do some previous request...\n";
}
void postRequest() {
std::cout << "do some post request...\n";
}
private:
std::shared_ptr<Subject> m_spSubject;
};
int main() {
auto rs = std::make_shared<RealSubject>();
Proxy proxy(rs);
proxy.request();
return 0;
}