Proxy Pattern

⭐ Interview Importance: LOW
⏱️ Revision Time: 1 min

Concept

Category: Structural Pattern

The Proxy Pattern provides a surrogate or placeholder for another object to control access to it.

A Proxy is an object that sits directly in front of the Real Object. It completely intercepts all requests intended for the Real Object. It can perform security checks, caching, or lazy-loading, and then optionally pass the request through to the Real Object.

The Mental Model

Imagine a CEO of a massive tech company.
You cannot just walk into their office and ask them a question.
You must go through their Executive Assistant (The Proxy).
The Assistant intercepts your request.

  • If you ask a trivial question, the Assistant answers it immediately (Caching) without bothering the CEO.
  • If you are not an employee, the Assistant kicks you out (Security/Access Control).
  • If you have a valid, critical issue, the Assistant finally opens the door and passes you through to the true CEO.

Types of Proxies

  1. Protection Proxy: Checks if the user has the correct authentication/permissions before allowing them to execute a sensitive method on the Real Object.
  2. Virtual Proxy (Lazy Loading): If the Real Object is a massive 10GB 3D Model, the Virtual Proxy displays a tiny placeholder image. It only actually instantiates and loads the 10GB object into RAM when the user explicitly clicks “Render”.
  3. Caching Proxy: Stores the results of expensive database queries. If the exact same query is requested, the Proxy returns the cached result, saving the Database from doing the work.

Implementation (Protection Proxy)

// 1. The Subject Interface
// Both the Real Object and the Proxy MUST implement this interface!
interface Server {
    handleRequest(url: string): void;
}

// 2. The Real Object (The VIP)
class RealServer implements Server {
    public handleRequest(url: string): void {
        console.log(`[RealServer] Processing massive data for ${url}...`);
    }
}

// 3. The Proxy (The Bodyguard)
class ProxyServer implements Server {
    private realServer: RealServer;

    constructor(realServer: RealServer) {
        this.realServer = realServer;
    }

    private checkAccess(url: string): boolean {
        console.log(`[Proxy] Checking security clearance for ${url}...`);
        // Reject any requests trying to access the admin panel
        if (url === "/admin") return false;
        return true;
    }

    private logAccess(url: string): void {
        console.log(`[Proxy] Logging access request to database...`);
    }

    public handleRequest(url: string): void {
        // Intercept!
        if (this.checkAccess(url)) {
            // Pass it through!
            this.realServer.handleRequest(url);
            this.logAccess(url);
        } else {
            console.log(`[Proxy] ACCESS DENIED: ${url}`);
        }
    }
}

// Usage:
const realServer = new RealServer();
// We wrap the real server in the Proxy
const proxy = new ProxyServer(realServer);

proxy.handleRequest("/home");
// Output: 
// [Proxy] Checking security clearance...
// [RealServer] Processing massive data...
// [Proxy] Logging access...

proxy.handleRequest("/admin");
// Output:
// [Proxy] Checking security clearance...
// [Proxy] ACCESS DENIED. (The Real Server was never touched!)

JavaScript Native Proxy API

Modern JavaScript has the Proxy pattern built directly into the language! The Proxy object allows you to intercept fundamental operations on a raw JS Object (like property lookup, assignment, enumeration).

const user = { name: "Alice", age: 30 };

const secureUser = new Proxy(user, {
    get(target, prop) {
        if (prop === "age") {
            return "ACCESS DENIED: Age is private!";
        }
        return target[prop]; // Pass through
    }
});

console.log(secureUser.name); // "Alice"
console.log(secureUser.age);  // "ACCESS DENIED: Age is private!"

This is the exact underlying mechanism that Vue 3 uses to build its entire Reactivity engine!

Interview Questions

Q: Proxy vs Decorator. They look identical in code (both wrap an object). What is the difference?
A: A Decorator is designed to add features (like adding Milk to Coffee). A Proxy is designed to control access (like a bodyguard). Furthermore, the client usually creates Decorators dynamically at runtime (new Milk(new Coffee())). A Proxy usually controls the lifecycle of its own object internally (Virtual Proxy), or is permanently hardcoded by the system, invisible to the client.