常见的代理模式的使用场景包括:
为其他对象提供一种代理以控制(隔离,使用接口)对这个对象的访问。
代理模式是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。在这个图例中,有几个关键组件和交互过程:
Client(客户端):客户端是发起请求的一方,它不知道真正的实体对象(Subject)是如何被实现和管理的。客户端通过代理(Proxy)来间接地与实体对象交互。
Subject(抽象主题/接口):这是一个定义了RealSubject和Proxy的共通接口的抽象类或接口。它声明了RealSubject和Proxy应该实现的方法,使得客户端能够通过相同的接口与它们交互。
RealSubject(真实主题):这是被代理的对象,它实现了Subject接口。RealSubject包含了执行实际业务逻辑的方法。
Proxy(代理):代理也是一个实现了Subject接口的对象。它持有对RealSubject的引用,并且可以控制对RealSubject的访问。代理可以在将请求传递给RealSubject之前或之后执行额外的操作,如权限检查、日志记录、事务管理等。
交互过程:
realSubject->Request(0);
所示,尽管这里的表示方式略显简化)。代理模式的主要优点包括:
这种模式在软件开发中非常有用,特别是当需要控制对某个对象的访问、减少系统组件之间的耦合度或者添加额外的处理逻辑时。
代理模式通常包括以下角色:
下面是一个简单的C++代码示例,展示了代理模式的实现:
Subject接口:
class Subject { public: virtual void request() = 0; virtual ~Subject() = default; };
RealSubject类:
#include class RealSubject : public Subject { public: void request() override { std::cout << "RealSubject: Handling request." << std::endl; } };
Proxy类:
class Proxy : public Subject { private: RealSubject* realSubject; public: Proxy() : realSubject(nullptr) {} ~Proxy() { delete realSubject; } void request() override { if (realSubject == nullptr) { realSubject = new RealSubject(); } std::cout << "Proxy: Logging the request." << std::endl; realSubject->request(); } };
客户端代码:
int main() { Proxy proxy; proxy.request(); // 实际请求通过代理进行 return 0; }
优点:
缺点:
下面是几个不同类型的代理模式的应用场景,并通过C++代码示例来说明每种场景的实现。
远程代理用于访问位于不同地址空间的对象。在这里,我们模拟一个简单的远程方法调用。
#include // Subject interface class Subject { public: virtual void request() = 0; virtual ~Subject() = default; }; // RealSubject implementation, which might be on a remote server class RealSubject : public Subject { public: void request() override { std::cout << "RealSubject: Handling request." << std::endl; } }; // Proxy implementation that handles communication with the remote RealSubject class RemoteProxy : public Subject { private: RealSubject* realSubject; public: RemoteProxy() : realSubject(nullptr) {} ~RemoteProxy() { delete realSubject; } void request() override { if (realSubject == nullptr) { std::cout << "RemoteProxy: Creating RealSubject remotely." << std::endl; realSubject = new RealSubject(); } std::cout << "RemoteProxy: Forwarding request to RealSubject." << std::endl; realSubject->request(); } }; // Client code int main() { RemoteProxy proxy; proxy.request(); // 实际请求通过代理进行 return 0; }
虚拟代理用于按需创建开销较大的对象。在这里,我们模拟一个按需加载图像的例子。
#include // Subject interface class Image { public: virtual void display() = 0; virtual ~Image() = default; }; // RealSubject implementation, which represents an actual image class RealImage : public Image { private: std::string filename; void loadFromDisk() { std::cout << "Loading " << filename << std::endl; } public: RealImage(const std::string& filename) : filename(filename) { loadFromDisk(); } void display() override { std::cout << "Displaying " << filename << std::endl; } }; // Proxy implementation that creates RealImage only when needed class ProxyImage : public Image { private: std::string filename; RealImage* realImage; public: ProxyImage(const std::string& filename) : filename(filename), realImage(nullptr) {} ~ProxyImage() { delete realImage; } void display() override { if (realImage == nullptr) { realImage = new RealImage(filename); } realImage->display(); } }; // Client code int main() { ProxyImage image("test.jpg"); image.display(); // Loading and displaying the image image.display(); // Displaying the already loaded image return 0; }
保护代理用于控制对原始对象的访问,可以对权限进行控制。这里我们模拟一个简单的权限控制例子。
#include // Subject interface class Subject { public: virtual void request() = 0; virtual ~Subject() = default; }; // RealSubject implementation, which represents an actual service class RealSubject : public Subject { public: void request() override { std::cout << "RealSubject: Handling request." << std::endl; } }; // Proxy implementation that controls access to RealSubject class ProtectionProxy : public Subject { private: RealSubject* realSubject; bool accessGranted; public: ProtectionProxy(bool access) : realSubject(new RealSubject()), accessGranted(access) {} ~ProtectionProxy() { delete realSubject; } void request() override { if (accessGranted) { std::cout << "ProtectionProxy: Access granted." << std::endl; realSubject->request(); } else { std::cout << "ProtectionProxy: Access denied." << std::endl; } } }; // Client code int main() { ProtectionProxy proxyWithAccess(true); proxyWithAccess.request(); // Access granted, forwarding request to RealSubject ProtectionProxy proxyWithoutAccess(false); proxyWithoutAccess.request(); // Access denied, not forwarding request return 0; }
智能引用代理在访问对象时执行一些附加操作,如引用计数、日志记录等。这里我们模拟一个记录访问日志的例子。
#include #include // Subject interface class Subject { public: virtual void request() = 0; virtual ~Subject() = default; }; // RealSubject implementation, which represents an actual service class RealSubject : public Subject { public: void request() override { std::cout << "RealSubject: Handling request." << std::endl; } }; // Proxy implementation that logs access to RealSubject class LoggingProxy : public Subject { private: std::shared_ptr realSubject; public: LoggingProxy() : realSubject(std::make_shared()) {} void request() override { std::cout << "LoggingProxy: Logging request." << std::endl; realSubject->request(); } }; // Client code int main() { LoggingProxy proxy; proxy.request(); // Logging the request and forwarding it to RealSubject return 0; }