Proxy pattern
The proxy pattern wraps an object to control access, add caching, or defer creation. Virtual, protection, and caching proxies all share one trick: same interface, different control.
Introduction
The Proxy pattern gives an object a stand-in that exposes the same interface while controlling access to the real object. The proxy can defer creation, cache results, enforce authorization, or coordinate another cross-cutting boundary without changing the caller's dependency.
TL;DR / mental model: Keep the same subject interface, put a gate in front of the real object, and make the gate decide whether, when, or how delegation happens.
Problem and Context
You're building an image gallery. Each Image loads a high-resolution file from disk, which takes 500ms and consumes 20MB of memory. The gallery shows 50 thumbnails, but users only click on a few. Loading all 50 upfront uses about 1GB of memory and adds about 25 seconds of serial loading work, even though most images may never be viewed.
You could add lazy-loading logic directly into HighResImage, but that mixes lifecycle management with image rendering. You could subclass it, but other parts of the system also need proxying (access control, caching). The proxy pattern fixes this by standing in for the real object with the same interface.
Here is what changes when you apply the Proxy pattern.
Participants and Structure
Image is the subject interface. RealImage is the heavy object that the proxy stands in for. Each proxy type implements Image but adds a different form of control: VirtualImageProxy defers creation, CachingImageProxy avoids redundant loads, and AccessControlProxy gates access by role. The client interacts with any Image without knowing which type it holds.
Idiomatic Example and Implementation Notes
The proxy pattern has three common variants. The image gallery demonstrates virtual, caching, and protection proxies, followed by Java's dynamic proxy for cases where writing a proxy class by hand is not practical.
Continue Reading with Premium
Unlock this article and every other in-depth system design guide on the platform with SDEpedia Premium.
Related Articles
The decorator pattern wraps objects to add behavior at runtime without modifying the original class. Stack decorators like layers, each adding one responsibility while keeping the same interface.
The adapter pattern wraps an incompatible third-party interface so your code can use it through an interface it already expects. Structural bridging without changing either side.
The facade pattern provides a single, simplified interface to a complex subsystem with many classes. Clients call one method instead of orchestrating five.