Java 3 min read

The Proxy Design Pattern: The Gatekeeper

Master the Proxy Pattern in Java. Learn how to control access to objects, implement lazy loading, and add security layers.

MR

Moshiour Rahman

Advertisement

The Problem: Expensive Objects

Imagine you have a HighResolutionImage class. Loading it consumes 500MB of RAM and takes 5 seconds because it downloads a 4K image from a server.

If your webpage has a list of 100 images, and you instantiate all HighResolutionImage objects at startup, your app will crash or freeze.

Most users won’t even scroll down to see them all. Why load them?

The Solution: The Proxy Pattern

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it. It allows you to perform magic (security check, lazy loading, logging) before the real object is called.

Real-Life Analogy: A Credit Card 💳

  • Real Money (The Real Subject): Using cash requires having physical bills. It’s bulky and risky.
  • Credit Card (The Proxy): It represents cash. When you swipe it, the bank checks if you have funds (Access Control) and then transfers the money later (Lazy Execution).

Visualizing the Pattern

Proxy Pattern

Implementation

1. The Interface

Common interface so the client can treat Proxy and RealObject identically.

public interface Image {
    void display();
}

2. The Real Object (Expensive)

public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk(); // Expensive operation happens at creation!
    }

    private void loadFromDisk() {
        System.out.println("Loading " + filename + " (Taking 5 seconds...)");
        try { Thread.sleep(500); } catch (Exception e) {}
    }

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

3. The Proxy (Lazy Loader)

public class ProxyImage implements Image {
    private RealImage realImage;
    private String filename;

    public ProxyImage(String filename) {
        this.filename = filename;
        // Note: RealImage is NOT created here. It's cheap to make a Proxy.
    }

    @Override
    public void display() {
        // Lazy Loading Logic
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

Usage

// Fast! No loading happens yet.
Image image = new ProxyImage("4k_photo.jpg"); 

System.out.println("Image created. Nothing loaded yet.");

// Only NOW does it load from disk
image.display(); 

// Second call uses cached version
image.display(); 

In The Wild (Real World Examples)

1. Hibernate / JPA (Lazy Loading)

When you fetch a User from the database, Hibernate returns a Proxy for the List<Order>. It doesn’t fetch the orders until you actually call user.getOrders().size().

2. Spring AOP (Aspect Oriented Programming)

When you add @Transactional to a method, Spring wraps your bean in a Proxy. The Proxy starts the transaction, calls your method, and then commits the transaction.

Cheat Sheet

FeatureDetails
CategoryStructural
Problem SolvedExpensive object creation, Access Control, Security
Key implementationif (realObj == null) realObj = new RealObj();
ProsPerformance (Lazy Loading), Security (Check permissions in Proxy)
ConsAdds complexity, hides the fact that a method call might be expensive

Tips to Remember 🧠

  • “The Gatekeeper”: A bodyguard or receptionist is a proxy. You have to go through them to see the CEO (Real Object).
  • Lazy vs Eager: Use Proxy when you want “Lazy Initialization”.

Advertisement

MR

Moshiour Rahman

Software Architect & AI Engineer

Share:
MR

Moshiour Rahman

Software Architect & AI Engineer

Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.

Related Articles

Comments

Comments are powered by GitHub Discussions.

Configure Giscus at giscus.app to enable comments.