Proxy Design Pattern in Java
Introduction
In software systems, there are scenarios where direct access to an object is undesirable. This could be due to security concerns, expensive object creation, or remote access. The Proxy Pattern provides a substitute or placeholder for another object to control access, delay creation, or add additional functionality.
Think of it like a bodyguard: you don’t meet a celebrity directly—you go through a bodyguard who controls access and protects them.
Definition
The Proxy Pattern is a structural design pattern that provides a surrogate or placeholder for another object. It controls access to the original object, allowing additional actions before or after forwarding requests.
Key Idea: The client interacts with a proxy instead of the real object, and the proxy handles requests, optionally delegating them to the real object.
Types of Proxies
- Virtual Proxy: Creates expensive objects only when needed (lazy loading).
- Protection Proxy: Controls access based on permissions or roles.
- Remote Proxy: Represents an object in a different address space (e.g., remote server).
- Smart Proxy: Adds extra functionality, like logging, caching, or reference counting.
When to Use the Proxy Pattern
- When object creation is resource-intensive and should be delayed.
- When access control is required for certain users or roles.
- When you want to hide the complexity of interacting with a remote object.
- To add additional functionality (logging, caching) without modifying the real object.
Real-World Example
- ATM card: Acts as a proxy to the bank account. It ensures proper authentication and access control before allowing transactions.
- Virtual Image Viewer: Loads large images lazily to save memory.
Java Implementation
Let’s implement a Virtual Proxy example for image loading.
Step 1: Define the Subject Interface
// Subject Interface
interface Image {
void display();
}
Step 2: Create the Real Subject
// Real Subject
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
Step 3: Create the Proxy Class
// Proxy
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
@Override
public void display() {
if (realImage == null) {
realImage = new RealImage(fileName); // Lazy loading
}
realImage.display();
}
}
Step 4: Client Usage
public class Main {
public static void main(String[] args) {
Image image1 = new ProxyImage("photo1.jpg");
Image image2 = new ProxyImage("photo2.jpg");
// Image will be loaded only when display() is called
image1.display();
image1.display(); // Already loaded, no additional load
image2.display();
}
}
Output:
Loading photo1.jpg
Displaying photo1.jpg
Displaying photo1.jpg
Loading photo2.jpg
Displaying photo2.jpg
Observation: The real image object is created only when needed, saving memory and processing.
Advantages of the Proxy Pattern
- Lazy Initialization: Creates expensive objects only when required.
- Access Control: Protects sensitive objects from unauthorized access.
- Logging and Auditing: Can add extra functionality without modifying real objects.
- Remote Access: Simplifies interaction with remote objects.
Disadvantages
- Extra Layer: Adds an additional layer of abstraction, which may increase complexity.
- Overhead: Proxy operations may add slight performance overhead.
- Complexity in Implementation: Managing multiple proxy types can make the codebase harder to maintain.
Summary
The Proxy Pattern is a powerful tool to control access, delay object creation, and enhance functionality without changing the real object. By acting as a surrogate, proxies simplify client interaction and improve system performance.
Next, we can continue with Behavioral Design Patterns, which focus on how objects interact and communicate, starting with the Observer Pattern, one of the most commonly used behavioral patterns.