Proxy Design Pattern in C# with Example

1. Definition

The Proxy Design Pattern provides a surrogate or placeholder for another object to control access to it. It can add a level of indirection to object access, allowing for additional operations, such as lazy initialization, logging, or access control, to be performed.

2. Problem Statement

Imagine you have a heavy object that consumes a lot of memory or requires significant resources to initialize. Instantiating this object every time it's needed can be inefficient. Additionally, you might want to control the access to this object, add logging, or delay its instantiation until it's really necessary.

3. Solution

The Proxy pattern suggests creating a new proxy class with the same interface as the original service object. This proxy class can then manage the lifecycle and access to the service object, allowing for operations like lazy instantiation, logging, and access control.

4. Real-World Use Cases

1. Lazy loading of large images in a graphic editor.

2. Access control to network resources.

3. Logging requests to a service.

5. Implementation Steps

1. Create an interface that both the RealObject and Proxy will implement.

2. Implement the RealObject that provides the actual functionality.

3. Implement the Proxy which contains a reference to the RealObject and controls access to it.

6. Implementation in C#

// Step 1: Create an interface
public interface IService
{
    void PerformOperation();
}

// Step 2: Implement the RealObject
public class RealService : IService
{
    public RealService()
    {
        // Simulating heavy initialization
        Console.WriteLine("RealService initialized!");
    }

    public void PerformOperation()
    {
        Console.WriteLine("RealService operation performed!");
    }
}

// Step 3: Implement the Proxy
public class ProxyService : IService
{
    private RealService _realService;

    public void PerformOperation()
    {
        if (_realService == null)
        {
            _realService = new RealService();
        }
        Console.WriteLine("ProxyService: Delegating operation to RealService...");
        _realService.PerformOperation();
    }
}

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Client: Using the proxy...");
        IService proxy = new ProxyService();
        proxy.PerformOperation();
    }
}

Output:

Client: Using the proxy...
ProxyService: Delegating operation to RealService...
RealService initialized!
RealService operation performed!

Explanation:

In the example above, the ProxyService controls the instantiation of RealService

The client interacts with the ProxyService without knowing about the RealService. Only when the PerformOperation method is called, the RealService is instantiated, simulating lazy instantiation.

7. When to use?

1. Use the Proxy pattern when you need to control access to an object, without clients knowing about this proxy layer.

2. When you want to defer the instantiation of an object until it is really needed.

3. When you want to add logging, access control, or other behaviors to object access.


Comments