Proxy Pattern¶
Intent¶
The Proxy pattern provides a surrogate or placeholder for another object to control access to it. A proxy acts as an intermediary, adding additional functionality before or after forwarding requests to the real object.
Problem¶
Sometimes you need to add extra functionality when accessing an object, but you don't want to modify the object itself:
- The object is in a remote location (network communication required)
- The object is expensive to create (lazy initialization desired)
- Access to the object needs to be controlled (security/permissions)
- You want to add logging, caching, or other cross-cutting concerns
- The object is a shared resource that needs reference tracking
Modifying the original object or creating subclasses for each concern leads to code duplication and violates the Single Responsibility Principle.
Solution¶
The Proxy pattern suggests creating a proxy class with the same interface as the real object. The proxy:
- Implements the same interface as the real object (Subject)
- Contains a reference to the real object
- Controls access to the real object
- Can add additional behavior before/after delegating to the real object
- Is transparent to clients (they use the same interface)
Structure¶
Participants¶
- Subject
- Defines the common interface for RealSubject and Proxy
- Allows Proxy to be used anywhere RealSubject is expected
- In our example:
Subjectinterface withrequest()method
- RealSubject
- Defines the real object that the proxy represents
- Contains the actual business logic
- In our example:
RealSubjectclass
- Proxy
- Maintains a reference to RealSubject
- Implements the same interface as RealSubject
- Controls access to RealSubject
- Can add additional functionality
- In our example:
Proxy,VirtualProxy,ProtectionProxy,CachingProxy
- Client - Works with objects through the Subject interface - Doesn't know whether it's using Proxy or RealSubject
Implementation¶
Subject Interface¶
Basic Proxy¶
Virtual Proxy (Lazy Initialization)¶
Protection Proxy (Access Control)¶
Caching Proxy (Performance)¶
Usage Example¶
Applicability¶
Use the Proxy pattern when:
- Lazy initialization (Virtual Proxy) - Delay expensive object creation until actually needed - Example: Large images, documents, database connections
- Access control (Protection Proxy) - Control access based on permissions - Example: Authentication, authorization, role-based access
- Remote proxy (Remote Proxy) - Represent an object in different address space - Example: RPC, REST API clients, distributed systems
- Logging/Monitoring (Logging Proxy) - Track operations on the object - Example: Audit logs, performance monitoring
- Caching (Caching Proxy) - Cache expensive operation results - Example: Database query caching, API response caching
- Smart reference (Smart Proxy) - Add additional housekeeping when object is accessed - Example: Reference counting, copy-on-write
Proxy Types¶
1. Virtual Proxy¶
Purpose: Lazy initialization of expensive objects
Use cases: - Large images that take time to load - Documents that should only be loaded when viewed - Database connections - Heavy resources
Benefits: - Faster application startup - Reduced memory usage - Better resource utilization
2. Protection Proxy¶
Purpose: Access control and security
Use cases: - Authentication and authorization - Role-based access control - Sensitive operations - Permission checking
Benefits: - Centralized security logic - Separation of concerns - Easy to modify access rules
3. Remote Proxy¶
Purpose: Represent object in different address space
Use cases: - Network communication (RPC, REST, SOAP) - Distributed systems - Microservices - Inter-process communication
Benefits: - Hides network complexity - Location transparency - Can add retry logic, connection pooling
4. Caching Proxy¶
Purpose: Cache expensive operation results
Use cases: - Database queries - API calls - Expensive computations - Frequent identical requests
Benefits: - Improved performance - Reduced server load - Lower latency
5. Smart Reference/Smart Proxy¶
Purpose: Additional housekeeping operations
Use cases: - Reference counting - Copy-on-write - Resource cleanup - Lock management
Benefits: - Automatic resource management - Memory optimization - Thread safety
6. Logging Proxy¶
Purpose: Log operations and track usage
Use cases: - Audit trails - Performance monitoring - Debugging - Usage analytics
Benefits: - Non-invasive logging - Centralized monitoring - Easy to enable/disable
Consequences¶
Benefits¶
-
Controlled access - Proxy controls when and how RealSubject is accessed - Can add security, validation, initialization logic
-
Lazy initialization - Defer expensive object creation until needed - Improves startup time and memory usage
-
Open/Closed Principle - Add functionality without modifying RealSubject - Extend behavior through composition
-
Single Responsibility Principle - Separate concerns (access control, logging, etc.) from business logic - Each proxy type has one responsibility
-
Transparency - Client code doesn't need to change - Proxy and RealSubject have same interface
Drawbacks¶
-
Increased complexity - Additional classes and indirection - More code to maintain
-
Performance overhead - Extra layer of indirection - May slow down operations (usually negligible)
-
Response delay - Some proxies may slow down responses - Lazy initialization adds delay on first use
Proxy vs Similar Patterns¶
Proxy vs Adapter¶
| Aspect | Proxy | Adapter |
|---|---|---|
| Intent | Control access to object | Make incompatible interfaces work |
| Interface | Same as real object | Different interface |
| Purpose | Add functionality, control access | Interface conversion |
| When | Before/after object access | Wrapping existing object |
Proxy vs Decorator¶
| Aspect | Proxy | Decorator |
|---|---|---|
| Intent | Control access | Add responsibilities |
| Management | Manages object lifecycle | Wraps existing object |
| Creation | Often creates RealSubject | Receives object to wrap |
| Transparency | Client may be unaware | Client explicitly decorates |
| Focus | Access control, lazy init | Enhance functionality |
Proxy vs Facade¶
| Aspect | Proxy | Facade |
|---|---|---|
| Intent | Control access to single object | Simplify complex subsystem |
| Interface | Same as RealSubject | New simplified interface |
| Subsystems | One object | Multiple subsystems |
| Relationship | IS-A (same interface) | HAS-A (contains subsystems) |
Real-world Examples¶
-
Remote Method Invocation (RMI) - Proxy: Local stub representing remote object - RealSubject: Remote server object - Handles network communication, serialization
-
ORM Lazy Loading - Proxy: Lazy loading proxy for entity relationships - RealSubject: Actual entity data from database - Loads related data only when accessed
-
Virtual Memory (OS) - Proxy: Page table entries - RealSubject: Physical memory pages - Loads pages from disk when accessed
-
Smart Pointers - Proxy: std::shared_ptr, std::unique_ptr - RealSubject: Raw pointer - Reference counting, automatic cleanup
-
Image Loading in Documents - Proxy: Placeholder/thumbnail - RealSubject: Full-resolution image - Loads full image when scrolled into view
-
Database Connection Pooling - Proxy: Pooled connection wrapper - RealSubject: Actual database connection - Reuses connections, manages lifecycle
-
CDN (Content Delivery Network) - Proxy: CDN edge servers - RealSubject: Origin server - Caches content closer to users
Implementation Considerations¶
1. Creating RealSubject¶
Options: - Proxy creates RealSubject (lazy initialization) - Client passes RealSubject to Proxy - Factory creates both
2. Reference to RealSubject¶
Considerations: - Store pointer/reference to RealSubject - Decide ownership (unique_ptr, shared_ptr) - Consider lifetime management
3. Overriding Only Some Operations¶
Proxy doesn't have to override all methods:
4. Copy-on-Write¶
Special case of Virtual Proxy:
5. Proxy Chains¶
Can chain multiple proxies:
Sample Output¶
Key Takeaways¶
- Proxy provides a surrogate/placeholder for another object to control access
- Proxy and RealSubject implement the same interface (transparency)
- Multiple proxy types: Virtual, Protection, Remote, Caching, Smart Reference
- Virtual Proxy enables lazy initialization of expensive objects
- Protection Proxy adds access control and security
- Caching Proxy improves performance through result caching
- Proxy can add functionality without modifying RealSubject (OCP)
- Different from Adapter (interface conversion) and Decorator (add responsibilities)
- Commonly used in ORMs, RPC systems, smart pointers, and image loading
- Manages object lifecycle, controls access, adds cross-cutting concerns