Proxy Pattern
Proxy Pattern: Controlling Object Access
Section titled “Proxy Pattern: Controlling Object Access”Now let’s explore the Proxy Pattern - a powerful structural design pattern that provides a placeholder or surrogate for another object to control access to it.
Why Proxy Pattern?
Section titled “Why Proxy Pattern?”Imagine you’re accessing a large file on a remote server. Instead of loading the entire file immediately (which is slow and expensive), you use a proxy that loads the file only when you actually need it. The Proxy Pattern works the same way - it provides a placeholder that controls access to the real object, adding functionality like lazy loading, access control, or caching.
The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. The proxy has the same interface as the real object, allowing it to be used interchangeably.
What’s the Use of Proxy Pattern?
Section titled “What’s the Use of Proxy Pattern?”The Proxy Pattern is useful when:
- You want lazy loading - Load expensive objects only when needed
- You want access control - Control who can access the object
- You want caching - Cache results to avoid expensive operations
- You want logging/monitoring - Track access to objects
- You want remote access - Access objects on remote servers
What Happens If We Don’t Use Proxy Pattern?
Section titled “What Happens If We Don’t Use Proxy Pattern?”Without the Proxy Pattern, you might:
- Load everything upfront - Expensive objects loaded even if not used
- No access control - Direct access to sensitive objects
- No caching - Expensive operations repeated unnecessarily
- Tight coupling - Clients directly depend on real objects
- Hard to add cross-cutting concerns - Logging, security scattered everywhere
Simple Example: The Image Loader
Section titled “Simple Example: The Image Loader”Let’s start with a super simple example that anyone can understand!
Visual Representation
Section titled “Visual Representation”Interaction Flow
Section titled “Interaction Flow”Here’s how the Proxy Pattern works in practice - showing how proxy controls access:
sequenceDiagram
participant Client
participant Proxy as ImageProxy
participant RealImage
Client->>Proxy: display()
activate Proxy
Proxy->>Proxy: Check if image loaded
alt Image not loaded
Proxy->>RealImage: load_from_disk()
activate RealImage
RealImage->>RealImage: Expensive loading operation
RealImage-->>Proxy: Image loaded
deactivate RealImage
Proxy->>Proxy: Cache reference
end
Proxy->>RealImage: display()
activate RealImage
RealImage-->>Proxy: Image displayed
deactivate RealImage
Proxy-->>Client: Displayed
deactivate Proxy
Note over Client,RealImage: Proxy loads image only\nwhen needed (lazy loading)!
The Problem
Section titled “The Problem”You’re building an image viewer. Loading images from disk is expensive. Without Proxy Pattern:
Problems:
- Loads everything upfront - All images loaded even if not used
- Slow startup - Expensive operations happen immediately
- High memory usage - All objects in memory at once
- No lazy loading - Can’t defer expensive operations
The Solution: Proxy Pattern
Section titled “The Solution: Proxy Pattern”Class Structure
Section titled “Class Structure”classDiagram
class Subject {
<<interface>>
+request() void
}
class RealSubject {
+request() void
}
class Proxy {
-real_subject: RealSubject
+request() void
-check_access() bool
-lazy_load() void
}
class Client {
+operation() void
}
Client --> Subject : uses
Proxy --> Subject : implements
Proxy --> RealSubject : controls access
RealSubject --> Subject : implements
note for Proxy "Controls access to RealSubject"
note for RealSubject "Expensive object"
Real-World Software Example: Database Query Proxy
Section titled “Real-World Software Example: Database Query Proxy”Now let’s see a realistic software example - a database system that needs to cache query results to avoid expensive database calls.
The Problem
Section titled “The Problem”You’re building a database access layer. Database queries are expensive. Without Proxy Pattern:
Problems:
- No caching - Same queries executed repeatedly
- Slow performance - Every query hits the database
- Unnecessary load - Database accessed even for cached queries
The Solution: Proxy Pattern
Section titled “The Solution: Proxy Pattern”Proxy Pattern Variants
Section titled “Proxy Pattern Variants”There are different types of proxies based on their purpose:
1. Virtual Proxy (Lazy Loading)
Section titled “1. Virtual Proxy (Lazy Loading)”Loads expensive objects only when needed:
Use case: Lazy loading of expensive resources
2. Protection Proxy (Access Control)
Section titled “2. Protection Proxy (Access Control)”Controls access to objects based on permissions:
Use case: Access control, security
3. Remote Proxy
Section titled “3. Remote Proxy”Represents objects on remote servers:
Use case: Remote method invocation, RPC
4. Caching Proxy
Section titled “4. Caching Proxy”Caches results to avoid expensive operations:
Use case: Caching, performance optimization
When to Use Proxy Pattern?
Section titled “When to Use Proxy Pattern?”Use Proxy Pattern when:
✅ You want lazy loading - Load expensive objects only when needed
✅ You want access control - Control who can access the object
✅ You want caching - Cache results to avoid expensive operations
✅ You want logging/monitoring - Track access to objects
✅ You want remote access - Access objects on remote servers
When NOT to Use Proxy Pattern?
Section titled “When NOT to Use Proxy Pattern?”Don’t use Proxy Pattern when:
❌ Simple objects - If object is simple, proxy adds unnecessary complexity
❌ No need for control - If you don’t need lazy loading, caching, or access control
❌ Performance critical - Proxy adds indirection (usually negligible)
❌ Over-engineering - Don’t add complexity for simple cases
Common Mistakes to Avoid
Section titled “Common Mistakes to Avoid”Mistake 1: Proxy Not Delegating Properly
Section titled “Mistake 1: Proxy Not Delegating Properly”Mistake 2: Not Maintaining Same Interface
Section titled “Mistake 2: Not Maintaining Same Interface”Mistake 3: Creating Real Object Unnecessarily
Section titled “Mistake 3: Creating Real Object Unnecessarily”Benefits of Proxy Pattern
Section titled “Benefits of Proxy Pattern”- Lazy Loading - Loads expensive objects only when needed
- Access Control - Controls who can access objects
- Caching - Caches results to avoid expensive operations
- Remote Access - Accesses objects on remote servers
- Separation of Concerns - Adds cross-cutting concerns without modifying real object
- Transparent - Client doesn’t know it’s using a proxy
Revision: Quick Catch-Up
Section titled “Revision: Quick Catch-Up”What is Proxy Pattern?
Section titled “What is Proxy Pattern?”Proxy Pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. The proxy has the same interface as the real object.
Why Use It?
Section titled “Why Use It?”- ✅ Lazy loading - Load expensive objects only when needed
- ✅ Access control - Control who can access objects
- ✅ Caching - Cache results to avoid expensive operations
- ✅ Remote access - Access objects on remote servers
- ✅ Separation of concerns - Add cross-cutting concerns
How It Works?
Section titled “How It Works?”- Define subject interface - Common interface for proxy and real object
- Implement real subject - The actual object
- Create proxy - Implements same interface, controls access
- Client uses proxy - Client interacts with proxy (transparent)
- Proxy delegates - Proxy delegates to real object when needed
Key Components
Section titled “Key Components”Client → Proxy → RealSubject- Subject - Interface for proxy and real object
- RealSubject - The actual object
- Proxy - Controls access to real subject
- Client - Uses proxy (doesn’t know it’s a proxy)
Simple Example
Section titled “Simple Example”class Proxy(Subject): def __init__(self): self._real_subject = None
def operation(self): if self._real_subject is None: self._real_subject = RealSubject() # Lazy load return self._real_subject.operation()When to Use?
Section titled “When to Use?”✅ Lazy loading
✅ Access control
✅ Caching
✅ Remote access
✅ Logging/monitoring
When NOT to Use?
Section titled “When NOT to Use?”❌ Simple objects
❌ No need for control
❌ Performance critical
❌ Over-engineering
Key Takeaways
Section titled “Key Takeaways”- Proxy Pattern = Controls access to real object
- Proxy = Placeholder with same interface
- RealSubject = Actual object
- Benefit = Lazy loading, caching, access control
- Use Case = Expensive resources, caching, security
Common Pattern Structure
Section titled “Common Pattern Structure”class Proxy(Subject): def __init__(self): self._real_subject = None
def operation(self): if self._real_subject is None: self._real_subject = RealSubject() return self._real_subject.operation()Remember
Section titled “Remember”- Proxy Pattern controls access to real objects
- It has the same interface as real object
- It’s about control, not just wrapping!
- Use it for lazy loading, caching, access control
- Keep it transparent - client shouldn’t know it’s a proxy!
Interview Focus: Proxy Pattern
Section titled “Interview Focus: Proxy Pattern”Key Points to Remember
Section titled “Key Points to Remember”1. Core Concept
Section titled “1. Core Concept”What to say:
“Proxy Pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. The proxy has the same interface as the real object, allowing it to be used interchangeably while adding functionality like lazy loading, caching, or access control.”
Why it matters:
- Shows you understand the fundamental purpose
- Demonstrates knowledge of when to use it
- Indicates you can explain concepts clearly
2. When to Use Proxy Pattern
Section titled “2. When to Use Proxy Pattern”Must mention:
- ✅ Lazy loading - Load expensive objects only when needed
- ✅ Access control - Control who can access objects
- ✅ Caching - Cache results to avoid expensive operations
- ✅ Remote access - Access objects on remote servers
- ✅ Logging/monitoring - Track access to objects
Example scenario to give:
“I’d use Proxy Pattern when building an image viewer. Loading images from disk is expensive. Instead of loading all images upfront, I create image proxies that load images only when they’re actually displayed. This improves startup time and reduces memory usage.”
Must discuss:
- Proxy: Controls access, same interface, adds functionality like lazy loading/caching
- Decorator: Adds behavior, same interface, wraps to enhance functionality
- Key difference: Proxy controls access, Decorator adds behavior
Example to give:
“Proxy Pattern controls access to an object and adds functionality like lazy loading or caching. Decorator Pattern adds behavior to an object dynamically. Proxy is about control and optimization, Decorator is about adding features. Proxy typically has one real object, Decorator can wrap multiple decorators.”
4. Proxy Variants
Section titled “4. Proxy Variants”Must discuss:
- Virtual Proxy: Lazy loading of expensive resources
- Protection Proxy: Access control and security
- Remote Proxy: Remote object access
- Caching Proxy: Caching expensive operations
Example to give:
“I use Virtual Proxy for lazy loading images, Protection Proxy for access control in a secure system, Remote Proxy for accessing objects on remote servers, and Caching Proxy for caching database query results. Each variant serves a specific purpose.”
5. Benefits and Trade-offs
Section titled “5. Benefits and Trade-offs”Benefits to mention:
- Lazy loading - Loads expensive objects only when needed
- Access control - Controls who can access objects
- Caching - Caches results to avoid expensive operations
- Separation of concerns - Adds cross-cutting concerns without modifying real object
- Transparent - Client doesn’t know it’s using a proxy
Trade-offs to acknowledge:
- Complexity - Adds abstraction layer
- Performance - Small overhead (usually negligible)
- Over-engineering risk - Can be overkill for simple cases
6. Common Interview Questions
Section titled “6. Common Interview Questions”Q: “What’s the difference between Proxy Pattern and Decorator Pattern?”
A:
“Proxy Pattern controls access to an object and adds functionality like lazy loading, caching, or access control. Decorator Pattern adds behavior to an object dynamically. Proxy is about control and optimization, Decorator is about adding features. Proxy typically manages one real object, Decorator can wrap multiple decorators in a chain.”
Q: “When would you use Virtual Proxy vs Caching Proxy?”
A:
“I use Virtual Proxy when I want to defer the creation of expensive objects until they’re actually needed - like loading images only when displayed. I use Caching Proxy when I want to cache the results of expensive operations - like caching database query results to avoid repeated queries.”
Q: “How does Proxy Pattern relate to SOLID principles?”
A:
“Proxy Pattern supports the Single Responsibility Principle by separating access control, caching, or lazy loading into the proxy. It supports the Open/Closed Principle - you can add functionality (proxy) without modifying the real object. It supports the Dependency Inversion Principle by having clients depend on the Subject interface rather than concrete implementations.”
Interview Checklist
Section titled “Interview Checklist”Before your interview, make sure you can:
- Define Proxy Pattern clearly in one sentence
- Explain when to use it (with examples showing lazy loading/caching)
- Describe Proxy vs Decorator Pattern
- Implement Proxy Pattern from scratch
- Compare with other structural patterns (Decorator, Adapter)
- List proxy variants (Virtual, Protection, Remote, Caching)
- List benefits and trade-offs
- Identify common mistakes (not delegating, different interface)
- Give 2-3 real-world examples
- Connect to SOLID principles
- Discuss when NOT to use it
Remember: Proxy Pattern is about controlling access to objects - providing a placeholder that adds functionality like lazy loading, caching, or access control! 🎯