1.抽象对象(Subject):定义了真实对象和代理对象的共同接口。
2.真实对象(RealSubject):又称为被代理对象,代理模式中的核心角色,定义了真正需要被代理的业务逻辑。
3.代理对象(Proxy):充当了客户端与真实对象之间的中介。
对应UML类图:
1.Subject定义了Proxy和RealSubject的公共接口。
2.Proxy和RealSubject都实现了Subject的接口。
3.客户端(Client)通过Proxy与RealSubject进行交互。
4.RealSubject负责完成主要的接口实现,Proxy负责控制外部Client对接口的访问。
5.Proxy内部包含对Subject的对象指针或引用,因此Proxy可以进一步调用子类RealSubject中的函数(forward calls)。
6.在某些情况下,Proxy可以用来完成RealSubject实例的创建与销毁。
7.Client是使用Proxy的对象,它通过Proxy来访问和操作RealSubject。
代码实现:
- #include
- using namespace std;
-
- class Subject
- {
- public:
- virtual void request() = 0;
- virtual ~Subject() {}
- };
-
- class RealSubject : public Subject
- {
- public:
- void request() {
- cout << "RealSubject.request()" << endl;
- }
- };
-
- class Proxy : public Subject
- {
- private:
- Subject* realSubject;
- public:
- Proxy()
- {
- realSubject = new RealSubject();
- }
- ~Proxy()
- {
- delete realSubject;
- }
- // Forward calls to the RealSubject:
- void request() {
- realSubject->request();
- }
- };
-
- int main() {
- Proxy p;
- p.request();
- }
运行结果:
RealSubject.request()
补充:在C++编码中,确实可以通过继承和虚函数实现父类调用子类的成员函数,这是C++多态特性的一种常见应用方式。
- #include
- using namespace std;
-
- class Base {
- public:
- virtual void print() {
- cout << "Base class method" << endl;
- }
- };
-
- class Derived : public Base {
- public:
- // 重写父类的虚函数
- virtual void print() override {
- cout << "Derived class method" << endl;
- }
- };
-
- int main() {
- // 父类对象调用子类方法
- Base* baseObj = new Derived();
- baseObj->print();
- }
运行结果:
Derived class method
简单代理(Simple Proxy):主要用于转发请求和处理一些基本操作,例如添加日志、计时等。
远程代理(Remote Proxy):当主体对象在另一个地址空间(如网络地址)时,远程代理会提供远程通信的功能,进行数据的访问和转换。
智能引用代理(Smart Reference Proxy):也称为共享代理,它维护了多个客户端对同一目标的共享引用,并提供统一的接口。
虚拟代理(Virtual Proxy):延迟针对昂贵资源的访问,只有在真正使用时才加载。
保护代理(Protection Proxy):主要用于访问权限的控制,比如身份验证、授权等。
1.延迟加载:使资源密集型的对象仅仅在被使用时才加载,例如,访问大型数据库、加载大批量图像数据等。
2.访问控制:代理可以通过添加身份验证来控制对真实主体的访问,可用于保护敏感数据。
3.缓存机制:代理可以缓存高频次的请求,从而减少系统开销,优化性能。
4.日志记录和监控:代理可用于记录或监控对真实主体执行的操作,而无需修改其代码。
5.远程访问:在分布式系统中,真实主体可能位于不同的计算机上,代理模式可以隐藏远程通信的复杂细节。
6.状态管理:代理可以同步管理多个客户端所共享的真实主体的状态,确保它们的一致性。
代理模式的优点:
可以在不修改被代理对象的情况下,增加额外的功能或控制访问方式。
可以在访问对象之前和之后进行一些处理,比如添加日志、添加时间戳等。
可以实现远程代理,使得客户端可以通过网络访问远程的对象。
可以防止未经授权访问真实主体。
代理模式的缺点:
引入新的类,增加代码复杂性。
读取资源时,需要通过代理来间接访问,造成额外的性能损失。
开发场景:基于Proxy模式来模拟对图片的延迟加载和显示控制。
1.创建Subject
- //Step 1: Define the Subject interface
- class Image {
- public:
- virtual void display() = 0;
- };
2.创建RealSubject
- //Step 2: Implement the Real Object
- class RealImage : public Image {
- private:
- std::string filename;
- public:
- RealImage(const std::string& filename) : filename(filename) {
- // Simulate loading the image
- std::cout << "Loading image: " << filename << std::endl;
- }
-
- void display() override {
- std::cout << "Displaying image: " << filename << std::endl;
- }
- };
3.Proxy类实现与RealSubject相同的接口,并维护对RealSubject的引用。
- //Step 3: Create the Proxy
- class ImageProxy : public Image {
- private:
- // Reference to the Real Object
- RealImage* realImage;
- std::string filename;
-
- public:
- ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}
-
- void display() override {
- if (realImage == nullptr) {
- realImage = new RealImage(filename);
- }
- realImage->display();
- }
- };
完整代码实现:
- #include
- #include
-
- using namespace std;
- class Image {
- public:
- virtual void display() = 0;
- };
-
- class RealImage : public Image {
- private:
- std::string filename;
- public:
- RealImage(const std::string& filename) : filename(filename) {
- // Simulate loading the image
- std::cout << "Loading image: " << filename << std::endl;
- }
-
- void display() override {
- std::cout << "Displaying image: " << filename << std::endl;
- }
- };
-
- class ImageProxy : public Image {
- private:
- // Reference to the Real Object
- RealImage* realImage;
- std::string filename;
-
- public:
- ImageProxy(const std::string& filename) : filename(filename), realImage(nullptr) {}
-
- void display() override {
- if (realImage == nullptr) {
- realImage = new RealImage(filename);
- }
- realImage->display();
- }
- };
-
- int main() {
- //Create a proxy to an image
- Image* image = new ImageProxy("example.jpg");
-
- //Display the image
- image->display();
-
- //Displaying the image again
- image->display();
-
- delete image;
- return 0;
- }
运行结果:
- Loading image: example.jpg
- Displaying image: example.jpg
- Displaying image: example.jpg
https://www.geeksforgeeks.org/proxy-pattern-c-design-patterns/
https://www.bogotobogo.com/DesignPatterns/proxy.php
https://design-patterns.readthedocs.io/zh-cn/latest/structural_patterns/proxy.html
https://refactoring.guru/design-patterns/proxy