Back to results for “Design Patterns in Java”
Java › Design Patterns in Java

How would you implement the Proxy pattern to add lazy initialization to an expensive-to-create object, and how does this differ structurally from the Decorator pattern despite both wrapping an object behind a shared interface?

Advanced

Answer

A Proxy implements the same interface as a real subject object, controlling access to it -- for lazy initialization specifically, the proxy defers actually creating the expensive real object until it's genuinely needed (the first real method call), transparently creating and delegating to it at that point -- structurally, Proxy and Decorator look nearly identical (both wrap an object behind a shared interface and delegate), but their INTENT differs: Proxy controls access to (or defers creation of) essentially one underlying object, while Decorator is specifically designed for composing multiple stacked behavior-adding layers onto an object that already exists.
public interface ExpensiveResource { void operation(); }

class RealExpensiveResource implements ExpensiveResource {
    public RealExpensiveResource() { /* expensive initialization, e.g. loading a large file */ }
    public void operation() { System.out.println("Operating"); }
}

class LazyProxy implements ExpensiveResource {
    private RealExpensiveResource real;
    public void operation() {
        if (real == null) { real = new RealExpensiveResource(); }  // created only on first actual use
        real.operation();
    }
}
Real-world example A reporting application wraps an expensive-to-construct ReportGenerator (which loads a large dataset on construction) in a LazyProxy, deferring that expensive initialization until a report is actually requested, avoiding the upfront cost entirely for application instances that never end up generating a report at all.

Common follow-ups: What other purposes does the Proxy pattern serve beyond lazy initialization (remote proxies, protection proxies, caching proxies)?;How does Java's built-in java.lang.reflect.Proxy relate to this design pattern conceptually?