Structural · DWG NO. 015

Proxy

Stand in for a real object to control access to it — lazily creating it, caching it, or gating who can reach it.

TypeStructural
ScopeSingle object
ComplexityLow
Common inLazy loading, caching, access control, rate limiting

You need to add a check before an object is used, without changing every call site

An image gallery shouldn't load full-resolution images until they actually scroll into view, and an admin API shouldn't run a query for a user without permission — but the code calling `image.render()` or `api.query()` shouldn't have to know any of that.

Same interface, extra behavior on the way through

The proxy implements the same interface as the real object. Callers hold the proxy and never know the difference; the proxy decides when (or whether) to forward the call to the real object underneath.

Clientrequest()Proxy(if allowed)RealObject

A caching proxy in front of a slow API call

The first call for a given id hits the real service; every later call for the same id returns the cached result instantly.

cache-proxy.js
const RealUserService = {
  async fetchUser(id) {
    console.log(`network: fetching user ${id}`);
    return { id, name: `User ${id}` };
  },
};

class CachingUserServiceProxy {
  #cache = new Map();

  async fetchUser(id) {
    if (this.#cache.has(id)) {
      console.log(`cache: hit for user ${id}`);
      return this.#cache.get(id);
    }
    const user = await RealUserService.fetchUser(id);
    this.#cache.set(id, user);
    return user;
  }
}

const service = new CachingUserServiceProxy();
await service.fetchUser(1); // network: fetching user 1
await service.fetchUser(1); // cache: hit for user 1

Trade-offs