The Proxy Pattern is a structural design pattern that provides a placeholder or surrogate object to control access to another object.

Instead of interacting with the real object directly, clients communicate with the proxy, which forwards requests to the real object while performing additional operations such as access control, lazy initialization, caching, or logging.

Because the proxy implements the same interface as the real object, the client remains unaware that an intermediary object exists.

The Proxy Pattern is commonly used for security, remote communication, lazy loading, caching, and resource management.

Structure

The Proxy Pattern consists of the following participants.

1. The Subject defines the common interface for both the proxy and the real object.
2. The Real Subject performs the actual business operation.
3. The Proxy implements the same interface while controlling access to the real subject.
4. The Client interacts only with the subject interface.

Java Implementation

Suppose an application stores confidential documents. Only users with the ADMIN role should be allowed to view the document. A proxy can perform the authorization check before delegating the request to the real object.

Create the subject interface.
public interface Document {
    void display();
}
Create the real subject.
public class ConfidentialDocument implements Document {
    @Override
    public void display() {
        System.out.println("Displaying confidential document.");
    }
}
Create the proxy.
public class DocumentProxy implements Document {
    private final String role;
    private Document document;

    public DocumentProxy(String role) {
        this.role = role;
    }

    @Override
    public void display() {

        if (!"ADMIN".equals(role)) {
            System.out.println("Access denied.");
            return;
        }

        if (document == null) {
            document = new ConfidentialDocument();
        }
        document.display();
    }
}
The client accesses the document through the proxy.
public class Main {
    public static void main(String[] args) {
        Document admin = new DocumentProxy("ADMIN");
        admin.display();

        Document guest = new DocumentProxy("USER");
        guest.display();
    }
}
Output:
Displaying confidential document.
Access denied.

How It Works?

The client interacts only with the Document interface and is unaware of whether it is communicating with the real object or a proxy.

When the display() method is invoked, the DocumentProxy first checks whether the user has the required permissions. If access is denied, the request is rejected immediately.

If access is permitted, the proxy lazily creates the ConfidentialDocument object if it has not already been instantiated. The request is then delegated to the real object.

This approach allows additional behaviour such as authorization, lazy initialization, logging, or caching to be introduced without modifying the real object's implementation.

Advantages

1. It controls access to the real object.
2. It supports lazy initialization, reducing unnecessary object creation.
3. It allows additional behaviour such as security, logging, or caching without modifying the real object.
4. The client remains unaware of whether it is communicating with the proxy or the real object.

Disadvantages

1. The additional proxy object increases the number of classes in the application.
2. Every request passes through an extra layer of indirection.
3. Complex proxy logic can make the overall design harder to understand.

JDK Examples

The Proxy Pattern appears throughout the Java ecosystem.

1. The java.lang.reflect.Proxy class creates dynamic proxy objects that intercept method calls before delegating them to the target object.

2. Frameworks such as Hibernate use proxy objects to implement lazy loading, creating entity objects only when they are first accessed.

Summary

The Proxy Pattern provides a surrogate object that controls access to another object while exposing the same interface.

By introducing an intermediary layer, the pattern enables features such as security, lazy loading, caching, logging, and remote access without changing the implementation of the real object.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer • Java • Python • Distributed Systems • AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

💬 Comments

Join the Discussion