代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。
代理模式的主要角色
-
Subject(抽象主题):定义真实主题和代理主题的共同接口
-
RealSubject(真实主题):实现真正的业务逻辑
-
Proxy(代理):包含对真实主题的引用,可以控制对真实主题的访问
代理模式的类型
-
虚拟代理:延迟创建开销大的对象
-
远程代理:为远程对象提供本地代表
-
保护代理:控制对原始对象的访问权限
-
智能引用代理:在访问对象时执行附加操作(如引用计数)
代码示例
#include <iostream>
#include <memory>
#include <string>
// 抽象主题
class Image {
public:
virtual ~Image() = default;
virtual void display() = 0;
};
// 真实主题
class RealImage : public Image {
public:
RealImage(const std::string& filename) : filename(filename) {
loadFromDisk();
}
void display() override {
std::cout << "Displaying " << filename << std::endl;
}
private:
void loadFromDisk() {
std::cout << "Loading " << filename << " from disk" << std::endl;
}
std::string filename;
};
// 代理
class ProxyImage : public Image {
public:
ProxyImage(const std::string& filename) : filename(filename), realImage(nullptr) {}
void display() override {
if (realImage == nullptr) {
realImage = std::make_unique<RealImage>(filename);
}
realImage->display();
}
private:
std::string filename;
std::unique_ptr<RealImage> realImage;
};
// 使用示例
int main() {
ProxyImage image1("photo1.jpg");
ProxyImage image2("photo2.jpg");
// 图像第一次显示时会从磁盘加载
image1.display();
// 图像已经加载过,直接从内存显示
image1.display();
// 另一个图像第一次显示
image2.display();
return 0;
}
UML结构
要点总结
1、"增加一层间接层"是软件系统中对许多复杂问题的一种常见解决方法。在面向对象系统中,直接使用某些对象会带来很多问题,作为间接层的proxy对象便是解决这一问题的常用手段。
2、具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。
3、Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。
代理模式的优点
-
可以控制对真实对象的访问
-
作为真实对象和客户端之间的中介,可以增加额外的功能
-
可以延迟真实对象的创建和初始化
-
可以实现远程访问
代理模式的缺点
-
可能会引入额外的复杂度
-
可能会增加响应时间(因为多了一层代理)
适用场景
-
需要延迟加载(Lazy Initialization)时
-
需要控制对原始对象的访问权限时
-
需要为远程对象提供本地接口时
-
需要为对象访问添加日志或监控时