动机
在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。
如何在不失去透明操作对象的同时来管理/控制这些对象特有的复 杂性?增加一层间接层是软件开发中常见的解决方式。
代码示例
class ISubject{
public:virtual void process();
};//Proxy的设计
class SubjectProxy: public ISubject{public:virtual void process(){//对RealSubject的一种间接访问//....}
};class ClientApp{ISubject* subject;public:ClientApp(){subject=new SubjectProxy();}void DoTask(){//...subject->process();//....}
};
Proxy模式定义
为其他对象提供一种代理以控制对这个对象的访问。
以下是一个简单的 C++ 代理模式的例子,其中实现了一个图片加载的代理。
#include <iostream>
#include <string>// Subject 接口
class Image {
public:virtual void display() const = 0;
};// RealSubject 类
class RealImage : public Image {
private:std::string filename;public:RealImage(const std::string& filename) : filename(filename) {loadImage();}void loadImage() {std::cout << "Loading image: " << filename << std::endl;}void display() const override {std::cout << "Displaying image: " << filename << std::endl;}
};// Proxy 类
class ImageProxy : public Image {
private:RealImage* realImage;std::string filename;public:ImageProxy(const std::string& filename) : realImage(nullptr), filename(filename) {}void display() const override {if (realImage == nullptr) {realImage = new RealImage(filename);}realImage->display();}
};// Client 代码
int main() {// 使用代理加载图片,实际图片加载在需要显示时进行Image* image = new ImageProxy("sample.jpg");// 第一次显示图片,会触发加载image->display();// 第二次显示图片,直接使用已加载的图片image->display();return 0;
}
在这个例子中,Image 是代理模式的 Subject 接口,RealImage 是 RealSubject 类,负责实际加载和显示图片。ImageProxy 是代理类,用于延迟加载和控制对 RealImage 对象的访问。客户端通过代理类使用图片,代理类在需要时创建或使用实际图片对象。
要点总结
“增加一层间接层”是软件系统中对许多复杂问题的一种常见解 决方法。在面向对象系统中,直接使用某些对象会带来很多问题, 作为间接层的proxy对象便是解决这一问题的常用手段。
具体proxy设计模式的实现方法、实现粒度都相差很大,有些可能对单个对象做细粒度的控制,如copy-on-write技术,有些可能对组件模块提供抽象代理层,在架构层次对对象做proxy。
Proxy并不一定要求保持接口完整的一致性,只要能够实现间接控制,有时候损及一些透明性是可以接受的。