Skip to contentJMRG
All posts

Proxy Pattern: Access Control and Optimization

design-patternsstructuralproxy

Intent

Proxy provides a substitute or placeholder for another object to control access to it. Useful for lazy loading, caching, access control, and logging.

Proxy Types

classDiagram
    class Subject {
        <<interface>>
        +request()
    }

    class RealSubject {
        +request()
    }

    class Proxy {
        -realSubject: RealSubject
        +request()
    }

    Subject <|.. RealSubject
    Subject <|.. Proxy
    Proxy --> RealSubject

Virtual Proxy (Lazy Loading)

interface Image {
  display(): void;
}

class RealImage implements Image {
  constructor(private filename: string) {
    this.loadFromDisk(); // Expensive
  }

  private loadFromDisk(): void {
    console.log(`Loading ${this.filename}...`);
  }

  display(): void {
    console.log(`Displaying ${this.filename}`);
  }
}

class ImageProxy implements Image {
  private realImage: RealImage | null = null;

  constructor(private filename: string) {}

  display(): void {
    if (!this.realImage) {
      this.realImage = new RealImage(this.filename);
    }
    this.realImage.display();
  }
}

Caching Proxy

class CachingProxy implements ApiClient {
  private cache = new Map<string, { data: unknown; expires: number }>();

  constructor(private client: ApiClient, private ttl = 60000) {}

  async fetch(endpoint: string): Promise<unknown> {
    const cached = this.cache.get(endpoint);

    if (cached && cached.expires > Date.now()) {
      return cached.data; // Cache HIT
    }

    const data = await this.client.fetch(endpoint);
    this.cache.set(endpoint, { data, expires: Date.now() + this.ttl });
    return data;
  }
}

When to Use

Type Use Case
Virtual Proxy Lazy loading heavy resources
Caching Proxy Reduce API/DB calls
Protection Proxy Access control
Logging Proxy Audit and metrics

Conclusion

Proxy is versatile for adding cross-cutting behavior without modifying the original object.