2.7 Proxy Pattern - Structural Design Pattern
The Proxy Pattern gives another item a stand-in or surrogate to manage access to it. This blog post will examine the Proxy Pattern, explain its composition, and look at an example of Java code that demonstrates how it is used.
What is the Proxy Pattern?
An item known as the genuine subject is accessed through a surrogate or placeholder that is provided by the Proxy Pattern. The primary goal of employing a proxy is to control access to the true subject by adding a layer of indirection. This has multiple applications, including data caching, slow initialization, access control, logging, and more.
Structure of Proxy Pattern
The Structural Proxy Pattern involves the following components:
Subject: This is an interface that defines the common interface for the RealSubject and Proxy classes. It allows the Proxy to be used anywhere the RealSubject is expected.
RealSubject: This is the real object that the Proxy represents. It implements the Subject interface and provides the actual functionality.
Proxy: This is the surrogate class that acts as an intermediary between the client and the RealSubject. It maintains a reference to the RealSubject and controls access to it, optionally performing additional functionality before or after forwarding the request to the RealSubject.
Java Code Example
Let's illustrate the Proxy Pattern with a simple example in Java. Consider a scenario where we have a Image
interface representing an image and a RealImage
class representing the actual image file. We'll create a ProxyImage
class to control access to the RealImage
object.
// Subject Interface
interface Image {
void display();
}
// RealSubject Class
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadImageFromDisk();
}
private void loadImageFromDisk() {
System.out.println("Loading image: " + filename);
}
@Override
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// Proxy Class
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);
}
realImage.display();
}
}
// Client Class
public class ProxyPatternExample {
public static void main(String[] args) {
// Client uses Proxy to access RealSubject
Image image1 = new ProxyImage("test1.jpg");
Image image2 = new ProxyImage("test2.jpg");
// Image 1 will be loaded from disk
image1.display();
// Image 1 will be displayed without loading from disk again
image1.display();
// Image 2 will be loaded from disk
image2.display();
}
}
In this example, RealImage
represents the actual image file, and ProxyImage
controls access to it. The first time an image is displayed, it is loaded from the disk, and subsequent display requests for the same image are served from memory, demonstrating lazy loading behavior.
Output:
Loading image: test1.jpg
Displaying image: test1.jpg
Displaying image: test1.jpg
Loading image: test2.jpg
Displaying image: test2.jpg
Conclusion
Access to objects can be managed in a flexible manner with the Structural Proxy Pattern, enabling the transparent integration of new functionality. You can improve the behavior of the original object without modifying its code by employing a proxy. Java applications can benefit from more modular, maintainable, and effective code if the Proxy Pattern is understood and used.
Subscribe to my newsletter
Read articles from Venu Madhav Emmadi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by