Proxy Pattern
Description
The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, providing additional functionality or controlling the access to the real object. This pattern is useful in scenarios where access control is required, additional functionality needs to be added before or after accessing a real object, or a lightweight representation of a heavy object is needed. The Proxy Pattern adds a level of indirection between the client and the real object, allowing for added functionality without modifying the client code. However, it also introduces complexity and can potentially impact performance. The Proxy Pattern is related to the Decorator Pattern, which focuses on adding new behaviors to an object dynamically.
Content
Proxy Pattern
Tool: Design Pattern Implementer
Created: 01/31/2024
Prompt
from abc import ABC, abstractmethod
class Subject(ABC):
@abstractmethod
def request(self) -> None:
pass
class RealSubject(Subject):
def request(self) -> None:
print("RealSubject: Handling request.")
class Proxy(Subject):
def __init__(self, real_subject: RealSubject) -> None:
self._real_subject = real_subject
def request(self) -> None:
if self.check_access():
self._real_subject.request()
self.log_access()
def check_access(self) -> bool:
print("Proxy: Checking access prior to firing a real request.")
return True
def log_access(self) -> None:
print("Proxy: Logging the time of request.")
def client_code(subject: Subject) -> None:
subject.request()
real_subject = RealSubject()
proxy = Proxy(real_subject)
client_code(proxy)
Design Pattern: Proxy Pattern
The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It acts as an intermediary between the client and the real object, providing additional functionality or controlling the access to the real object.
Code Explanation
The given code snippet demonstrates the implementation of the Proxy Pattern. Here's how each component works:
Subject
(Interface): Defines the common interface for the RealSubject and Proxy classes by declaring therequest
method.RealSubject
: Implements theSubject
interface and defines its own implementation of therequest
method. It represents the real object that the client wants to access.Proxy
: Implements theSubject
interface and maintains a reference to theRealSubject
. It checks access permissions before allowing theRealSubject
to handle the request. It performs additional tasks before and after calling theRealSubject
.client_code
: Accepts aSubject
object as a parameter and invokes itsrequest
method. The client interacts with theSubject
object without directly accessing theRealSubject
.
Code Template
from abc import ABC, abstractmethod
class Subject(ABC):
@abstractmethod
def request(self) -> None:
pass
class RealSubject(Subject):
def request(self) -> None:
print("RealSubject: Handling request.")
class Proxy(Subject):
def __init__(self, real_subject: RealSubject) -> None:
self._real_subject = real_subject
def request(self) -> None:
if self.check_access():
self._real_subject.request()
self.log_access()
def check_access(self) -> bool:
print("Proxy: Checking access prior to firing a real request.")
return True
def log_access(self) -> None:
print("Proxy: Logging the time of request.")
def client_code(subject: Subject) -> None:
subject.request()
real_subject = RealSubject()
proxy = Proxy(real_subject)
client_code(proxy)
Example Usage
In the given example, the RealSubject
handles the request. However, before the RealSubject
handles the request, the Proxy
performs certain tasks, such as checking access permissions and logging the time of the request.
The client code interacts with the Subject
object (in this case, the Proxy
) without being aware of the RealSubject
. This indirection provides flexibility and allows additional functionality to be added without modifying the client code.
Applicability
The Proxy Pattern is applicable in scenarios where:
- Access control is required for a resource.
- Additional functionality needs to be added before or after accessing a real object.
- A lightweight representation of a heavy object is needed.
Benefits
- Provides a level of indirection between the client and the real object.
- Allows additional functionality to be added without modifying the client.
- Provides a way to control access to the real object.
- Can be used for remote communication, caching, logging, and other cross-cutting concerns.
Drawbacks
- Adds complexity by introducing an extra layer between the client and the real object.
- Can impact performance due to the overhead of the proxy.
Related Design Patterns
- Decorator Pattern: Similar to the Proxy Pattern, both involve wrapping an object to add additional functionality. However, the Proxy Pattern focuses on controlling access to the real object, while the Decorator Pattern focuses on adding new behaviors to an object dynamically.