Proxy Pattern

Stand an object with the same interface in front of the real one so you can delay, deny, cache or log access without the caller knowing.

Overview

The problem it solves Sometimes you do not want a caller to reach an object directly. The object is expensive to create and may never be used. Or only some callers may touch it. Or it lives on another machine. Or its answers are worth remembering. A proxy is an object with the same interface as the real one. The caller talks to the proxy, and the proxy decides whether, when and how to reach the real object.

The pattern is a structural pattern from the Gang of Four book (Gamma, Helm, Johnson and Vlissides, *Design Patterns*, 1994). Its roles are Subject (the shared interface), RealSubject (the object doing the work) and Proxy (the stand-in that controls access and usually holds or creates the real subject).

The kinds of proxy The book names four: remote, virtual, protection and smart reference. Caching and logging proxies are common additions that use the same shape.

  • Virtual — When to create the real object — An image that loads its pixels on first render()
  • Protection — Whether this caller may proceed — A document that checks a role before edit()
  • Remote — How to reach an object in another process — A client stub that turns a method call into a network request
  • Smart reference — Extra work on each access — Reference counting, locking, loading a persisted object
  • Caching — Whether to call at all — Return the last answer for the same arguments
  • Logging — Record each access, then pass through — An audit trail of every call

How a caching proxy answers The proxy sits on the call path, so it can short-circuit it. The first call goes through; the second one never reaches the real object.

A runnable example A virtual proxy and a protection proxy for the same subject. The asserts prove the real object is not built until it is needed, and that the deny path never reaches it.

Proxies you already use | Where | What the proxy does | Source | |---|---|---| | java.lang.reflect.Proxy | Builds a class at run time that implements a list of interfaces; every call is dispatched to one InvocationHandler.invoke method | Java SE API | | Spring AOP | Wraps a bean in a JDK dynamic proxy when the target implements an interface, else in a CGLIB subclass; that is how transactions and security interceptors run around a method | Spring Framework reference | | Hibernate lazy fetching | A proxy stands in for an entity or collection whose state is not loaded yet; the first method call fetches it. After the session closes the proxy can no longer fetch and throws LazyInitializationException | Hibernate 6 introduction | | Collections.unmodifiableList | A read-through view of a list; every mutating call throws UnsupportedOperationException | Java SE API | | Python getattr | Called only when normal attribute lookup fails, so a class that defines it can forward unknown attributes to a wrapped object in a few lines | Python data model |

Reverse proxies and API gateways are the same idea at the network level: the client sends a request to an address that looks like the service, and the intermediary authenticates, limits and logs before forwarding it.

Proxy next to its look-alikes | Pattern | Same interface? | Who creates the wrapped object | Intent | |---|---|---|---| | Proxy | Yes | Often the proxy itself (virtual, remote) | Control access | | Decorator | Yes | The caller, and decorators stack | Add behavior | | Adapter | No, it changes the interface | The caller | Make an existing class fit | | Facade | New, simpler interface | The caller or the facade | Simplify a subsystem |

What you will be able to do - Draw Subject, RealSubject and Proxy and explain why the client cannot tell them apart. - Name the kinds of proxy and pick the right one for lazy loading, authorization, caching or remote calls. - Write a virtual proxy whose asserts prove the real object was not created early. - Explain how Java dynamic proxies and Spring AOP proxies work, and the Hibernate lazy-loading trap. - Tell Proxy from Decorator by intent and by who creates the wrapped object.

Interview questions

  • What kinds of proxy are there, and how do you pick one?
  • How is Proxy different from Decorator when the code looks the same?
  • How do Java dynamic proxies and Spring AOP proxies work?
  • Write a generic proxy in Python without repeating every method.
  • What goes wrong with proxies in practice?

Sign up free to read the full topic

More Low-Level Design topics

Start free on Cariara · Coding problems · System design studio