注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。
控制对象访问的智能中介
1. 模式定义与用途
核心思想
- 代理模式:为其他对象提供一种**代理(替代品)**以控制对这个对象的访问。
- 关键用途:
1.延迟加载:仅在需要时创建开销大的对象(如图像懒加载)。
2.访问控制:校验权限或过滤请求(如敏感操作代理)。
3.远程服务:本地代理隐藏网络通信细节(如RPC调用)。
经典场景
- 虚拟代理:大图加载前的占位符。
- 保护代理:接口访问权限验证。
- 日志代理:记录操作历史或性能指标。
2. 模式结构解析
UML类图
+---------------------+ +---------------------+
| Subject | | Proxy |
+---------------------+ +---------------------+
| + request(): void |<|---- ---| - realSubject: RealSubject |
+---------------------+ | + request(): void |
^ +---------------------+
| ^
| |
+---------------------+ +---------------------+
| RealSubject | | Client |
+---------------------+ +---------------------+
| + request() |
+---------------------+
角色说明
Subject:抽象接口,定义客户端和代理的共同操作(如request())。-
RealSubject:真实对象,完成核心业务逻辑。 Proxy:代理类,控制对RealSubject的访问,可附加额外逻辑。
3. 现代C++实现示例
场景1:虚拟代理(图像懒加载)
#include <iostream>
#include <memory>
#include <string>
// 抽象图像接口
class Image {
public:
virtual ~Image() = default;
virtual void display() = 0;
};
// 真实对象:高分辨率图像(加载开销大)
class HighResImage : public Image {
public:
HighResImage(const std::string& path) : path_(path) {
loadFromDisk();
}
void display() override {
std::cout << "显示图像: " << path_ << "\n";
}
private:
void loadFromDisk() {
std::cout << "从磁盘加载大图: " << path_ << "(耗时操作)\n";
}
std::string path_;
};
// 代理:延迟加载图像
class LazyImageProxy : public Image {
public:
LazyImageProxy(const std::string& path) : path_(path) {}
void display() override {
if (!realImage_) {
realImage_ = std::make_unique<HighResImage>(path_);
}
realImage_->display();
}
private:
std::unique_ptr<Image> realImage_;
std::string path_;
};
// 客户端代码
int main() {
LazyImageProxy proxy("wallpaper.jpg");
// 图像未加载
proxy.display(); // 首次调用触发加载
}
/* 输出:
从磁盘加载大图: wallpaper.jpg(耗时操作)
显示图像: wallpaper.jpg
*/
场景2:保护代理(权限验证)
#include <unordered_map>
// 用户权限系统
class User {
public:
User(const std::string& role) : role_(role) {}
const std::string& getRole() const { return role_; }
private:
std::string role_;
};
// 敏感操作接口
class Database {
public:
virtual void executeQuery(const std::string& query, const User& user) = 0;
};
// 真实数据库
class RealDatabase : public Database {
public:
void executeQuery(const std::string& query, const User& user) override {
std::cout << "执行查询: " << query << "\n";
}
};
// 保护代理:检查权限
class SecureDatabaseProxy : public Database {
public:
SecureDatabaseProxy() : realDb_(std::make_unique<RealDatabase>()) {}
void executeQuery(const std::string& query, const User& user) override {
if (user.getRole() == "admin") {
realDb_->executeQuery(query, user);
} else {
std::cout << "拒绝访问:用户权限不足\n";
}
}
private:
std::unique_ptr<Database> realDb_;
};
// 使用示例
User admin("admin");
User guest("guest");
SecureDatabaseProxy proxy;
proxy.executeQuery("DELETE * FROM users", admin); // 允许
proxy.executeQuery("SELECT * FROM logs", guest); // 拒绝
4. 应用场景示例
场景1:远程服务代理(RPC客户端)
// 远程服务接口(客户端存根)
class RemoteService {
public:
virtual std::string fetchData(int id) = 0;
};
// 真实服务(模拟网络调用)
class RemoteServiceImpl : public RemoteService {
public:
std::string fetchData(int id) override {
// 模拟网络请求
return "Data for ID " + std::to_string(id);
}
};
// 本地代理(缓存与重试逻辑)
class RemoteServiceProxy : public RemoteService {
public:
RemoteServiceProxy() : service_(std::make_unique<RemoteServiceImpl>()) {}
std::string fetchData(int id) override {
if (cache_.find(id) != cache_.end()) {
return cache_[id];
}
// 模拟重试机制
for (int i = 0; i < 3; ++i) {
try {
auto data = service_->fetchData(id);
cache_[id] = data;
return data;
} catch (const std::exception& e) {
std::cout << "第 " << i + 1 << " 次重试...\n";
}
}
throw std::runtime_error("远程服务不可用");
}
private:
std::unique_ptr<RemoteService> service_;
std::unordered_map<int, std::string> cache_;
};
场景2:日志代理(操作审计)
class OrderService {
public:
virtual void placeOrder(const std::string& item) = 0;
};
class RealOrderService : public OrderService {
public:
void placeOrder(const std::string& item) override {
std::cout << "下单商品: " << item << "\n";
}
};
class LoggingProxy : public OrderService {
public:
LoggingProxy(std::unique_ptr<OrderService> service)
: service_(std::move(service)) {}
void placeOrder(const std::string& item) override {
log("用户尝试下单: " + item);
service_->placeOrder(item);
log("下单成功: " + item);
}
private:
void log(const std::string& message) {
std::cout << "[日志] " << message << "\n";
}
std::unique_ptr<OrderService> service_;
};
5. 优缺点分析
| 优点 | 缺点 |
|---|---|
| 解耦客户端与真实对象 | 增加系统复杂度(需维护代理类) |
| 支持访问控制与附加逻辑(日志/缓存) | 可能引入轻微性能开销(代理层调用) |
| 优化资源利用(如懒加载) | 过度使用会导致代码冗余 |
6. 调试与优化策略
调试技巧(VS2022)
1. 代理调用跟踪:
- 在代理类的fetchData()或executeQuery()设置断点,验证逻辑是否正确触发。
2. 验证权限与缓存:
- 使用 监视窗口 检查代理类中的cache_或用户角色状态。
性能优化
1. 线程安全缓存:
#include <mutex>
class ThreadSafeProxy : public RemoteService {
public:
std::string fetchData(int id) override {
std::lock_guard<std::mutex> lock(cacheMutex_);
// ... 原有缓存逻辑
}
private:
std::mutex cacheMutex_;
};
2. 延迟初始化优化:
class LazyInitProxy : public Image {
public:
void display() override {
if (!realImage_) {
realImage_ = std::make_unique<HighResImage>(path_);
}
realImage_->display();
}
};
&spm=1001.2101.3001.5002&articleId=146060931&d=1&t=3&u=fc10e8396188490c83d98ed495b6f9d2)
2947

被折叠的 条评论
为什么被折叠?



