STRUCTURAL PATTERNS / OBJECT DESIGN BRIEF

Proxy pattern

The Proxy pattern provides a stand-in object with the same interface as a real object to control access to it.

IntermediatePhase 05 / Topic 7 of 7ResponsibilitiesCollaborationsExtensibility
01

Overview

The Proxy pattern provides a stand-in object with the same interface as a real object to control access to it. The client talks to the proxy as if it were the real thing; the proxy decides when and how to forward calls. Common kinds are virtual proxies (lazy loading), protection proxies (authorization), remote proxies (network calls), and caching proxies.

Structurally identical to Decorator, the difference is intent: a proxy controls access to the subject (whether, when, where it is called), while a decorator adds new behavior. Frameworks use proxies heavily: ORM lazy loading, Spring's @Transactional, and RPC client stubs.

A company receptionist

Visitors ask for the CEO; the receptionist checks appointments, may take a message, and only then lets someone through. Visitors interact with the receptionist as the CEO's point of contact.

02

When to use it

  • Expensive objects should load lazily.
  • Access must be checked (permissions, quotas).
  • The real object lives elsewhere (remote service).
  • Results can be cached transparently.
03

Where it shows up in interviews

Access control

Recognize it when: only authorized users can call certain methods.

  • Design a document service with permissions
  • Design an internet access proxy
Lazy loading

Recognize it when: expensive resources loaded on demand.

  • Design an image viewer
  • Design an ORM lazy relation
04

Where it is used in real software

Hibernate lazy loading

Entity relations are proxies that query the database only when accessed.

Spring AOP

@Transactional and @Cacheable work by wrapping beans in proxies.

JavaScript Proxy and gRPC stubs

ES Proxy intercepts property access; gRPC clients are remote proxies for server methods.

05

Key terms

Subject
Interface shared by proxy and real object.
Real subject
The object doing the actual work.
Virtual proxy
Creates the real object on first use.
Protection proxy
Checks permissions before forwarding.
Remote proxy
Represents an object in another process.
06

How it works, step by step

  1. 1
    Define the subject interface

    ImageLoader, DocumentService.

  2. 2
    Implement the real subject

    Does the work.

  3. 3
    Implement the proxy

    Same interface; holds or creates the real subject.

  4. 4
    Add control logic

    Lazy creation, auth checks, caching, remoting.

  5. 5
    Give clients the proxy

    They cannot tell the difference.

07

Kinds of proxies

Same interface, different control

Step 1 / 4
Proxy typeControlsExample
VirtualWhen the object is createdLoad a high-res image only when displayed
ProtectionWho can callOnly owners can delete a document
RemoteWhere it runsgRPC stub calling a server
CachingWhether to call at allReturn cached exchange rates

NOWProxy type: Virtual | Controls: When the object is created | Example: Load a high-res image only when displayed

All kinds share the same interface as the real subject, so clients stay unchanged.

08

Implementation

interface DocumentService {  read(docId: string, user: User): Promise<string>;  delete(docId: string, user: User): Promise<void>;} type User = { id: string; roles: string[] }; class RealDocumentService implements DocumentService {  async read(docId: string) { return `content of ${docId}`; }  async delete(docId: string) { console.log("deleted", docId); }} class ProtectedDocumentService implements DocumentService {  constructor(private real: DocumentService, private owners: Map<string, string>) {}   async read(docId: string, user: User) {    return this.real.read(docId, user); // everyone can read  }   async delete(docId: string, user: User) {    const isOwner = this.owners.get(docId) === user.id;    if (!isOwner && !user.roles.includes("admin")) throw new Error("Forbidden");    return this.real.delete(docId, user);  }}
09

Complexity and performance

Proxy overhead1 check + delegation

Tiny for local proxies.

Remote proxyNetwork round trip

Hidden latency.

10

Trade-offs

Transparency vs surprises

Hiding network calls or lazy loading behind a normal interface can cause unexpected latency (N+1 queries).

Indirection

Another layer to debug; framework-generated proxies can confuse stack traces.

11

Variants and related techniques

Dynamic proxies

java.lang.reflect.Proxy and ES Proxy generate proxies at runtime.

Smart reference

Counts references or logs accesses.

12

Common mistakes

  • Lazy proxies causing N+1 queries.

    Fix: Fetch eagerly when you know data will be needed.

  • Self-invocation bypassing Spring proxies.

    Fix: Calls within the same class skip the proxy; move the method or call through the bean.

13

Interview questions

Proxy vs Decorator?

Same structure. Proxy controls access to the subject (lazy creation, permissions, remoting, caching); Decorator adds new responsibilities to it. Proxies usually manage the subject's lifecycle; decorators are given the wrapped object.

How does Spring's @Transactional work?

Spring wraps the bean in a proxy that begins a transaction before delegating to the real method and commits or rolls back afterward.

14

Practice problems

ProblemDifficultyWhat it trains
Lazy-loading image galleryEasyVirtual proxy.
Rate-limited API client proxyMediumAccess control.