结构型模式--Proxy代理模式
代理模式简介:
客户端通过代理对象来访问实际的服务对象。代理控制着客户端对服务对象的访问,可以在发送请求给服务对象的前后进行自定义处理。代理类和服务类应都实现自同一个接口,这样既可以在不改变客户端和服务器端代码的情况下增加新的代理类,同时对客户端来说不必关心访问的到底是服务器还是代理。
代理模式适合的部分应用场景(即代理模式的类型):
1. 保护代理
实现访问控制功能,如果希望只有拥有权限的客户对象才可以使用服务对象,就可以使用此模式。比如访问系统的操作日志,客户对象为普通用户,通过代理对象进行操作,代理判断权限不足不提供服务。当然访问控制也可以在服务端进行实现,如果服务端是不开放源代码的第三方库,那么就可以要代理模式。
2. 远程代理
适用于服务对象在远程服务器上的情况,代理通过网络传递客户请求,对客户端屏蔽一系列复杂的操作(例如请求封包解包、数据解析等)。对客户端来说和调用本地服务对象的过程相同。
3. 日志记录代理
适用于当需要保存对于服务对象的请求历史记录时。 代理可以在向服务传递请求前进行记录。
4. 虚拟代理
如果有一个偶尔使用的重量级服务对象, 一直保持该对象运行会消耗系统资源时, 可使用代理模式。无需在程序启动时就创建该对象, 可将对象的初始化延迟到真正有需要的时候。
代理模式的优点
1. 可以在客户端毫无察觉的情况下控制服务对象
2. 可以对服务对象的生命周期进行管理(如果客户端对服务对象的声明周期没有特殊要求)
3. 代理可以在服务对象还未创建的时候就开始工作
4. 可以在不对服务类或客户端类做出修改的情况下创建新的代理类
代理模式的缺点:
1. 服务响应可能会出现延迟
2. 代码可能会变得稍微复杂一些,因为要多创建一些类
保护代理的示例代码:
#include <iostream>
using namespace std;
//公共接口
class IServer
{
public:
virtual void doWork()=0;
};
//服务类
class RealServer :public IServer
{
public:
void doWork() { cout << "real_server work." << endl; }
};
//代理类
class Proxy :public IServer
{
public:
Proxy(RealServer* server) :_server(new RealServer(*server)){ }
bool checkAccess() const {
cout << "check access.\n";
return true;
}
void doWork() {
/*服务对象调用之前的控制操作,例如访问控制*/
if (checkAccess()) {
/* 委托给服务对象 */
_server->doWork();
}
}
private:
RealServer*_server;
};
//客户端调用代码
void clientInvoke(IServer* server)
{
server->doWork();
}
int main()
{
RealServer* real_server = new RealServer();
clientInvoke(real_server);
Proxy* proxy = new Proxy(real_server);
clientInvoke(proxy);
}