Proxy Pattern
The Proxy is a structural design pattern that provides a surrogate or placeholder for another object (the "real subject") to control access to it. It acts as an intermediary, adding functionality like lazy loading, access control, caching, or logging without modifying the real subject. According to Refactoring Guru, it's ideal when you need to protect, optimize, or extend access to an object indirectly.
Key Principles
- Indirection: Client interacts with proxy, unaware of the real subject.
- Transparency: Proxy mimics the real subject's interface.
- Control: Proxy can defer creation, validate calls, or add behavior.
Structure
- Subject: Common interface for real subject and proxy.
- Real Subject: The actual object (e.g., expensive resource).
- Proxy: Implements subject interface; holds reference to real subject; adds logic (e.g., check access before delegating).
- Client: Uses subject interface.
Python Example: Image Proxy (Lazy Loading)
from abc import ABC, abstractmethod
# Subject Interface
class Image(ABC):
@abstractmethod
def display(self):
pass
# Real Subject (expensive to load)
class RealImage(Image):
def __init__(self, filename):
self.filename = filename
self._load_from_disk() # Simulate expensive operation
def _load_from_disk(self):
print(f"Loading {self.filename} from disk... (expensive)")
def display(self):
print(f"Displaying {self.filename}")
# Proxy (controls access with lazy loading)
class ProxyImage(Image):
def __init__(self, filename):
self.filename = filename
self.real_image = None
def display(self):
if self.real_image is None:
self.real_image = RealImage(self.filename) # Lazy load
self.real_image.display()
# Client Code
if __name__ == "__main__":
image1 = ProxyImage("photo1.jpg")
image2 = ProxyImage("photo2.jpg")
print("Displaying image1:")
image1.display() # Loads from disk
print("\nDisplaying image1 again:")
image1.display() # Uses cached real image (no reload)
print("\nDisplaying image2:")
image2.display() # Loads from disk
Output:
Displaying image1:
Loading photo1.jpg from disk... (expensive)
Displaying photo1.jpg
Displaying image1 again:
Displaying photo1.jpg
Displaying image2:
Loading photo2.jpg from disk... (expensive)
Displaying photo2.jpg
Types of Proxies (Per Refactoring Guru)
- Virtual Proxy: Lazy loading (as above).
- Protection Proxy: Access control (e.g., check permissions).
- Remote Proxy: For distributed systems (e.g., stub for network object).
- Smart Proxy: Caching/logging (e.g., cache results).
When to Use Proxy
- Expensive Operations: Delay creation (e.g., large files, DB connections).
- Access Control: Validate before delegating (e.g., auth checks).
- Avoid: Simple objects (overhead).
Summary: Proxy provides a stand-in object that controls or enhances access to a real one, adding features like lazy loading or security without changing the subject.