Proxy pattern in LLD - System Design Guide
This diagram shows the client interacting with the proxy, which controls access to the real object.
### Before (no proxy) ### class RealImage: def __init__(self, filename): print(f"Loading image from {filename}") self.filename = filename def display(self): print(f"Displaying {self.filename}") image = RealImage("photo.jpg") image.display() ### After (with proxy) ### class RealImage: def __init__(self, filename): print(f"Loading image from {filename}") self.filename = filename def display(self): print(f"Displaying {self.filename}") class ProxyImage: 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) self.real_image.display() proxy_image = ProxyImage("photo.jpg") proxy_image.display() # Loads and displays proxy_image.display() # Displays without loading again
Practice
What is the main purpose of the Proxy pattern in system design?
Solution
Step 1: Understand the Proxy pattern role
The Proxy pattern acts as a stand-in or placeholder to control access to another object.Step 2: Compare options with the pattern definition
Only To control access to an object by using a placeholder correctly describes controlling access using a placeholder, which matches the Proxy pattern.Final Answer:
To control access to an object by using a placeholder -> Option BQuick Check:
Proxy pattern = control access placeholder [OK]
- Confusing Proxy with Singleton pattern
- Thinking Proxy modifies the real object directly
- Assuming Proxy replaces the real object permanently
Which of the following is the correct way to declare a proxy class that implements the same interface as the real object?
interface Image {
void display();
}
// Which proxy class declaration is correct?Solution
Step 1: Recall interface implementation syntax
In many languages, a class implements an interface using the 'implements' keyword, not 'extends'.Step 2: Check each option's correctness
class ImageProxy implements Image { void display() { /* control access */ } } correctly declares a class implementing the interface. class ImageProxy extends Image { void display() { /* control access */ } } wrongly uses 'extends' for an interface. class ImageProxy { void display() { /* control access */ } } misses interface implementation. interface ImageProxy implements Image { void display(); } wrongly declares an interface implementing another interface.Final Answer:
class ImageProxy implements Image { void display() { /* control access */ } } -> Option DQuick Check:
Proxy class implements interface = class ImageProxy implements Image { void display() { /* control access */ } } [OK]
- Using 'extends' instead of 'implements' for interfaces
- Not implementing the interface at all
- Declaring proxy as an interface instead of a class
Given the following code snippet, what will be the output?
class RealImage {
void display() { System.out.println("Displaying real image"); }
}
class ProxyImage {
RealImage realImage;
void display() {
if (realImage == null) {
realImage = new RealImage();
}
realImage.display();
}
}
ProxyImage proxy = new ProxyImage();
proxy.display();
proxy.display();Solution
Step 1: Analyze the first call to display()
Since realImage is null initially, it is created and then display() prints "Displaying real image".Step 2: Analyze the second call to display()
realImage is no longer null, so display() is called directly again, printing the same message.Final Answer:
Displaying real image Displaying real image -> Option AQuick Check:
Lazy loading calls display twice [OK]
- Assuming display prints only once
- Expecting NullPointerException due to uninitialized realImage
- Thinking proxy suppresses output
Identify the error in the following proxy implementation and select the fix:
class Proxy {
RealObject real;
void request() {
real.request();
}
}Solution
Step 1: Identify the problem in the code
The proxy calls real.request() but 'real' is never initialized, causing a NullPointerException.Step 2: Determine the correct fix
Initializing 'real' before calling request() ensures the real object exists and avoids errors.Final Answer:
Initialize 'real' before calling request() -> Option CQuick Check:
Uninitialized real causes error; initialize it [OK]
- Ignoring null initialization error
- Changing method names unnecessarily
- Removing proxy defeats pattern purpose
You are designing a system where loading a large image file is expensive. You want to use the Proxy pattern to improve performance by loading the image only when needed. Which of the following design choices best applies the Proxy pattern for this scenario?
Solution
Step 1: Understand the problem context
Loading large images is expensive, so delaying loading until necessary improves performance.Step 2: Match design choices to Proxy pattern benefits
Create a proxy class that holds the image filename and loads the real image only when display() is called uses lazy loading by deferring real image loading until display() is called, which fits Proxy pattern use.Final Answer:
Create a proxy class that holds the image filename and loads the real image only when display() is called -> Option AQuick Check:
Lazy loading with proxy = Create a proxy class that holds the image filename and loads the real image only when display() is called [OK]
- Loading real object immediately defeats proxy benefit
- Duplicating data wastes resources
- Replacing with thumbnail changes object behavior
Ready to prove it?
Pass the test and this pattern moves unknown
