远程代理(Remote Proxy)示例
假设有一个服务器应用程序,该应用程序提供了一个服务,比如获取用户信息。客户端直接访问远程对象可能很复杂,因此可以使用代理对象来简化这个过程。代理对象将请求转发给远程对象,远程对象负责真正的服务逻辑。
设计:
- Subject:定义了客户端和代理对象以及真实对象都共享的接口。
- RealSubject:实现了具体的服务操作,比如从远程数据库获取数据。
- Proxy:在客户端和远程对象之间起到中介作用,负责请求的转发。
代码示例:
#include <iostream>
#include <string>
#include <memory>
// 定义Subject接口
class UserService {
public:
virtual void getUserInfo(int userId) = 0;
virtual ~UserService() = default;
};
// 真实的UserService类,它提供了从远程数据库获取用户信息的功能
class RealUserService : public UserService {
public:
void getUserInfo(int userId) override {
std::cout << "Fetching user info from remote server for user ID: " << userId << std::endl;
}
};
// 代理类,它充当客户端和远程服务之间的中介
class ProxyUserService : public UserService {
private:
std::shared_ptr<RealUserService> realUserService;
bool isAuthenticated;
public:
ProxyUserService() : realUserService(nullptr), isAuthenticated(false) {}
// 设置认证信息
void authenticate(const std::string& token) {
if (token == "valid_token") {
isAuthenticated = true;
std::cout << "Authentication successful!" << std::endl;
} else {
std::cout << "Authentication failed!" << std::endl;
}
}
void getUserInfo(int userId) override {
// 代理对象在此控制对真实对象的访问权限
if (isAuthenticated) {
if (!realUserService) {
realUserService = std::make_shared<RealUserService>();
}
realUserService->getUserInfo(userId);
} else {
std::cout << "Access denied. Please authenticate first." << std::endl;
}
}
};
int main() {
// 创建代理对象
ProxyUserService proxyService;
// 尝试访问真实服务,未认证
proxyService.getUserInfo(101);
// 用户认证
proxyService.authenticate("valid_token");
// 认证后,访问真实服务
proxyService.getUserInfo(101);
return 0;
}
解释:
- UserService 是一个接口,声明了客户端和代理对象都需要实现的方法。
getUserInfo
方法是要调用的远程服务。 - RealUserService 是实际的远程服务,它执行从数据库或服务器获取用户信息的逻辑。
- ProxyUserService 是代理类,它负责客户端与真实服务之间的交互,提供认证功能,确保只有经过认证的用户才能访问真实的服务。
代理模式的复杂性:
- 延迟加载:
ProxyUserService
会在首次请求时创建RealUserService
对象,避免了不必要的远程服务调用。 - 认证控制:在代理中添加了访问控制,确保只有通过认证的用户可以访问真实服务。它模拟了一个实际的安全机制。
- 远程通信:虽然此示例并未直接涉及网络编程,但可以将
RealUserService
替换为通过网络与远程服务器通信的代码,进而实现真正的远程服务访问。
经典场景:
- 分布式系统:远程代理可以作为客户端与远程服务之间的中介,简化客户端对远程服务的调用。
- 访问控制:保护代理在许多应用中用于控制对敏感资源的访问,比如数据库访问,确保只有授权用户可以执行特定操作。