3.7. Proxy

Maheshmaddi
4 min readApr 9, 2023

--

The Proxy pattern is a structural design pattern that provides a surrogate or placeholder object for another object, controlling access to it. Proxies can be used for various purposes, such as lazy loading, access control, logging, or remote object access.

The Proxy pattern is typically used when:

  1. You need to control access to an object, either by adding extra functionality before or after the actual operation, or by restricting access based on certain conditions.
  2. You want to defer the full cost of creating an object until it is actually needed (lazy loading).
  3. You want to represent a remote object locally, hiding the complexity of remote communication.

To implement the Proxy pattern, follow these steps:

  1. Define an interface or abstract class for the subject that specifies the common methods for both the real object and the proxy.
  2. Create a concrete subject class that implements the common interface or extends the abstract class.
  3. Create a proxy class that also implements the common interface or extends the abstract class, and maintains a reference to the subject object.
  4. Implement the proxy methods to control access to the subject, adding extra functionality or delegation as needed.

Here’s a simple example of the Proxy pattern in Java:

// Subject interface
public interface Subject {
void operation();
}

// Real subject
public class RealSubject implements Subject {
@Override
public void operation() {
System.out.println("RealSubject operation");
}
}

// Proxy class
public class Proxy implements Subject {
private RealSubject realSubject;

@Override
public void operation() {
System.out.println("Proxy operation");
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.operation();
}
}

// Client code
public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.operation(); // Outputs: "Proxy operation", "RealSubject operation"
}
}

In this example, the Subject interface represents the common interface for both the real object and the proxy. The RealSubject class implements the Subject interface, while the Proxy class also implements the Subject interface and maintains a reference to a RealSubject object.

Advantages of the Proxy pattern:

  1. Improved control: The Proxy pattern allows for better control over access to the real object, enabling extra functionality or access control.
  2. Separation of concerns: The Proxy pattern separates the actual functionality of the real object from additional concerns like access control or lazy loading, promoting a cleaner and more modular codebase.

Disadvantages of the Proxy pattern:

  1. Increased complexity: The Proxy pattern introduces additional classes and interfaces, which can increase the overall complexity of the code.

When using the Proxy pattern, consider its benefits and drawbacks carefully. Use the pattern when you need to control access to an object, defer object creation, or represent remote objects locally. Be aware of the potential complexity introduced by the pattern and ensure that the pattern is applied judiciously to maintain a clean and understandable codebase.

Use Case: Image Loading and Display

This use case demonstrates the usage of the Proxy pattern to load and display images in a Java application. The Proxy pattern is employed to create a proxy object that can perform additional tasks, such as lazy loading or caching, while accessing the actual image object.

Here’s the Java code for the Proxy pattern use case:

  1. Image Interface:
public interface Image {
void display();
}

2. RealImage Class (the actual image object):

public class RealImage implements Image {
private String fileName;

public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}

@Override
public void display() {
System.out.println("Displaying " + fileName);
}

private void loadFromDisk(String fileName) {
System.out.println("Loading " + filename);
}
}

3. ProxyImage Class (the proxy object):

public 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();
}
}

4. Main Class to demonstrate the Proxy pattern:

public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_image.jpg");

// Image will be loaded and displayed for the first time.
image.display();
System.out.println("");

// Image will not be loaded again, but will be displayed.
image. Display();
}
}

In this example, the ProxyImage class acts as a proxy for the RealImage class. When the client calls the display() method on the ProxyImage, it checks if the RealImage object has been created. If not, it creates a new RealImage object, loads the image, and displays it. If the RealImage object has already been created, the proxy simply calls the display() method on the real object without loading the image again, thereby improving the application's performance.

Note: For complete list of design patterns click here

--

--