Proxy
Proxy is a structural pattern that places a surrogate object in front of the real object to control access. The Client sends requests through the same interface to the Proxy, and the Proxy performs additional logic -- access control, caching, lazy loading -- before delegating to the real object when necessary. Think of an executive's assistant. External contacts go through the assistant rather than reaching the executive directly. The assistant checks schedules, assesses urgency, and sometimes handles things without involving the executive at all. The requester uses the same communication channel regardless, so the difference is invisible.
βΆArchitecture Diagram
π StructureDashed line animations indicate the flow direction of data or requests
Direct access to an object is simple, but reality often makes it impractical. Creating database connections on every call is expensive. Letting anyone access sensitive data creates security risks. Using a remote object as if it were local requires network calls. If you solve these problems by sprinkling conditionals into client code, business logic and infrastructure logic become entangled. Access-control code spreads to every call site, and every policy change requires editing multiple locations.
Proxy is classified as a structural pattern in the GoF design patterns. As distributed systems became common, Remote Proxy -- treating remote objects as local -- gained early attention. Distributed technologies such as Java RMI and CORBA used the Proxy pattern as a core mechanism. Today, Proxy's use has broadened. JavaScript's Proxy object, Spring's AOP proxies, ORM lazy loading, API Gateways, and reverse proxy servers all operate on the same principle. The structure of 'placing a surrogate in front of the real target to handle additional logic' repeats from the programming-language level all the way to the infrastructure level.
Proxy's key property is maintaining the same interface as the real object. The Client depends only on the Subject interface and does not know whether a Proxy or the Real Subject is behind it. The sequence works like this: 1. The Client calls the Subject interface's `request()`. 2. Inside the Proxy's `request()`, pre-processing runs: permission checks, cache lookups, log entries. 3. If pre-processing passes, the Real Subject's `request()` is called via delegation. 4. The Real Subject's result goes through post-processing (cache storage, metric recording) and is returned to the Client. Variants differ by purpose. A Virtual Proxy defers creation of a heavy object until first use. A Protection Proxy verifies the caller's permissions. A Caching Proxy stores results of identical requests to reduce real calls. The structure is the same; only the pre- and post-processing logic changes.
Proxy and Decorator are nearly identical in structure. Both wrap a target object, implement the same interface, and delegate internally. The difference is intent. Proxy exists to control or manage access; Decorator exists to add functionality dynamically. Proxy often manages the target object's lifecycle, while Decorator typically receives the target from the outside. Proxy and Adapter are also compared. Proxy maintains the same interface and controls access; Adapter changes the interface itself. Whether the interface changes or stays the same is the criterion that separates them. 'Is this wrapping meant to control access, add functionality, or change the interface?' -- answering that question tells you whether Proxy, Decorator, or Adapter is the right choice.
Commonly Compared Concepts
Decorator
A structural pattern that dynamically adds behavior to an object
Proxy controls access, while Decorator adds functionality to the same interface. The structure is the same but the intent and lifecycle management differ.
Adapter
A structural pattern that bridges incompatible interfaces
Proxy maintains the same interface and controls access, while Adapter transforms the interface itself into a different shape.
Facade
A structural pattern that provides a simple entry point to a complex subsystem
Proxy controls access to a single object, while Facade bundles multiple subsystems behind a single simple interface.
Proxy appears often when separating infrastructure concerns from business logic. In Spring, adding `@Transactional` causes the framework to create a Proxy around the class that automatically wraps transaction begin and commit. The developer writes only business logic. ORM lazy loading is also Proxy. When `user.getOrders()` is called, a real DB query fires, but when the user object was loaded, only a Proxy was placed in the orders field, deferring the actual query. Cost is incurred only when needed. However, excessive Proxy use makes debugging harder. When multiple proxies stack in the call chain, tracing the path to the real logic becomes difficult, and additional logic can fire at unexpected points. In most cases, a single Proxy is sufficient.