Java Language – 92 – Proxy

Design Patterns – Proxy
Introduction to the Proxy Design Pattern

The Proxy pattern is a structural design pattern that provides a surrogate or a placeholder for another object to control access to it. It allows you to add an additional level of control, often used for lazy loading, access control, logging, or monitoring. The Proxy pattern is particularly useful when you want to postpone the creation and initialization of a resource-intensive object until it’s actually needed.

Key Components of the Proxy Pattern

The Proxy pattern consists of the following key components:

  • Subject: The Subject is an interface or an abstract class that defines the common interface for both the Real Subject and the Proxy. It declares the methods that the Proxy and Real Subject must implement.
  • Real Subject: The Real Subject is the actual object that the Proxy represents. It implements the Subject interface and provides the concrete implementation of the methods declared in the Subject.
  • Proxy: The Proxy is an object that implements the Subject interface as well. It maintains a reference to the Real Subject and controls access to it. The Proxy can perform additional tasks such as lazy initialization, access control, or logging before delegating the request to the Real Subject.
Types of Proxies

There are several types of proxies in the design pattern, including:

  • Virtual Proxy: A Virtual Proxy is used for lazy initialization. It creates the Real Subject object only when a method is called on it. Until then, it holds a reference to the Real Subject without initializing it.
  • Remote Proxy: A Remote Proxy is used to represent an object that is in a different address space, such as when dealing with remote services or distributed systems.
  • Cache Proxy: A Cache Proxy is used to manage the results of expensive operations, caching the results of requests to the Real Subject to improve performance.
Implementing the Proxy Pattern

Let’s implement a simple example of the Proxy pattern in Java to illustrate its usage. In this example, we’ll create a Image interface representing an image and two classes: RealImage as the real image object and ProxyImage as the proxy for controlling access to the real image.


// Subject interface
interface Image {
    void display();
}

// Real Subject
class RealImage implements Image {
    private String filename;

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

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

    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// Proxy
class ProxyImage implements Image {
    private RealImage realImage;
    private String filename;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

public class ProxyPatternExample {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("image1.jpg");
        Image image2 = new ProxyImage("image2.jpg");

        // The Real Image objects are created only when needed
        image1.display(); // Loads and displays image1.jpg
        image2.display(); // Loads and displays image2.jpg
    }
}

In this example, the ProxyImage controls access to the real images, ensuring that they are created only when needed. The proxy initializes the RealImage object and delegates the display operation to it when required.

Usage of the Proxy Pattern

The Proxy pattern is used in various scenarios, including:

  • Lazy Loading: Creating resource-intensive objects only when they are actually needed.
  • Access Control: Implementing security and access control for sensitive objects.
  • Logging: Adding logging, monitoring, or profiling to the behavior of objects.
Benefits of the Proxy Pattern

The Proxy pattern offers several advantages:

  • Control: It provides an additional layer of control over access to objects.
  • Performance: It can improve performance by postponing object creation and initialization.
  • Security: It enhances security by implementing access control mechanisms.
Conclusion

The Proxy design pattern is a valuable tool for controlling access to objects and adding additional functionalities without modifying the original object. It is widely used in various software applications to achieve lazy loading, access control, logging, and other requirements.