DEV Community

Cover image for Design Patterns Simplified: Part 16 — Proxy Pattern (a.k.a. “The Gatekeeper”)
Prateek Prabhakar
Prateek Prabhakar

Posted on • Edited on • Originally published at Medium

Design Patterns Simplified: Part 16 — Proxy Pattern (a.k.a. “The Gatekeeper”)

The Proxy Pattern belongs to the Structural category.
Why? Because it controls access to an object by providing a placeholder or “proxy” that manages how and when the real object is accessed.

Think of it like, you want to enter a VIP party, but first, you meet the gatekeeper.
The gatekeeper checks your invitation and only lets you in if everything is good. You don’t talk to the party organizer directly. It is the gatekeeper who controls your access.


The Image Viewer

Suppose you are building an Image Viewer app that loads high resolution images. Loading these images is slow and uses a lot of memory.

You don’t want to load every image at once when the gallery opens. Instead, you want to load an image only when the user actually wants to see it.

So, the challenge here is - How do you delay loading the heavy image without changing how the rest of the app accesses it?

Enter the Proxy Pattern

The Proxy Pattern provides a placeholder object (proxy) that looks like the real object and controls access to it. The proxy implements the same interface as the real object, so the app can use it seamlessly.
But the proxy handles the loading or access logic, for example, loading the image only when requested.

What does the code look like?

//Step 1: Define the Image interface
Interface Image
    Method Display()

//Step 2: Real Image Class
Class RealImage implements Image
    Property filename

    Constructor(filename)
        this.filename = filename
        LoadFromDisk()

    Method LoadFromDisk()
        Print "Loading " + filename + " from disk..."

    Method Display()
        Print "Displaying " + filename

//Step 3: Proxy Image Class
Class ProxyImage implements Image
    Property realImage
    Property filename

    Constructor(filename)
        this.filename = filename
        this.realImage = null

    Method Display()
        If realImage == null Then
            // Load image only when needed
            realImage = new RealImage(filename)  
        End If
        realImage.Display()

// Caller Logic
images = [new ProxyImage("photo1.jpg"), new ProxyImage("photo2.jpg")]
// Images are NOT loaded yet

images[0].Display()  // Loads and displays photo1.jpg
images[1].Display()  // Loads and displays photo2.jpg
images[0].Display()  // Displays photo1.jpg without loading again

Enter fullscreen mode Exit fullscreen mode

ProxyImage looks just like RealImage because both implement the same Image interface.
But the proxy controls when the real image is loaded. It loads the image only when Display() is called for the first time.
This saves memory and improves performance without changing how the rest of the app uses the images.

What Did We Achieve?

  • Controlled access to a heavy object.
  • Delayed expensive object creation until needed (lazy loading). Lazy loading is implemented by delaying the creation (and loading) of the RealImage object until the Display() method is actually called.
  • Kept client code unchanged by using the same interface for proxy and real object.

When Should You Use the Proxy Pattern?

  • When you want to control access to an object (security, logging).
  • When creating the real object is expensive, and you want to delay it until necessary.
  • When you want to add extra functionality (like caching or access control) without changing the real object.

Use Cases?

  • Virtual Proxy: Lazy loading large images, files, or data.
  • Remote Proxy: Representing an object in a different address space (e.g. across a network).
  • Protection Proxy: Controlling access based on permissions.
  • Logging Proxy: Logging access to the real object’s methods.

Is the Proxy Pattern Confused with Any Other Pattern?

Yes. It is often confused with the Decorator Pattern.
Both deal with object structure, but here is the difference,
Proxy: Controls access and can delay or restrict it.
Decorator: Adds new behaviors dynamically without controlling access.


To summarize, it would be apt to say,

The Proxy Pattern is like having a gatekeeper who controls when and how you get access to something valuable, making your system efficient and secure.

Hope this helped you understand the Proxy Pattern clearly!

Next up: Flyweight Pattern. Let’s learn about it…

Top comments (0)