TypeScript Proxy Pattern Example

1. Definition

The Proxy pattern is a structural design pattern that provides an object representing another object. By providing a surrogate or placeholder for another object, a proxy can control access to it.

2. Problem Statement

There are situations where direct access to an object is not desirable or possible. This might be due to the need for controlled or delayed access, or because creating and maintaining the real object is expensive in terms of time or resources.

3. Solution

Introduce a new proxy class that stands as an intermediary between the client and the real object. The proxy class can add extra functionalities, manage resource-intensive operations, or delay the instantiation of the real object until it's necessary.

4. Real-World Use Cases

1. Lazy initialization where an object is created only when it's actually needed.

2. Access control proxies that add an authentication layer before granting access to the real service.

3. Logging proxies that record requests made to the real object.

5. Implementation Steps

1. Define a common interface for the RealObject and Proxy to ensure interchangeability.

2. Implement the RealObject with all its functionalities.

3. Create the Proxy class which holds a reference to a RealObject.

4. Depending on the proxy type, implement the required functionalities in the Proxy class.

6. Implementation in TypeScript

// Step 1: Define a common interface
interface Subject {
    request(): void;
}
// Step 2: Implement the RealObject
class RealObject implements Subject {
    request(): void {
        console.log('RealObject: Handling request.');
    }
}
// Step 3: Create the Proxy class
class ProxyObject implements Subject {
    private realObject: RealObject;
    constructor() {
        this.realObject = new RealObject();
    }
    request(): void {
        if (this.checkAccess()) {
            this.realObject.request();
            this.logAccess();
        }
    }
    private checkAccess(): boolean {
        // Some access validation logic here
        console.log('Proxy: Checking access...');
        return true;
    }
    private logAccess(): void {
        console.log('Proxy: Logging the time of request.');
    }
}
// Usage:
const proxy = new ProxyObject();
proxy.request();

Output:

Proxy: Checking access...
RealObject: Handling request.
Proxy: Logging the time of request.

Explanation:

The Proxy pattern introduces an intermediary (the proxy) that holds a reference to the real object. 

In our TypeScript example, the ProxyObject acts as a placeholder for the RealObject. The proxy can handle operations itself, like checking access and logging, and delegates the main operation to the real object.

7. When to use?

The Proxy pattern is useful when:

1. You want to introduce a layer between your application and a third-party service or library.

2. Objects require a virtual proxy for lazy instantiation.

3. Access control for the original object is required.

4. There's a need for a sophisticated reference mechanism for an object, like reference counting.


Comments