The Proxy design pattern is a structural design pattern that provides a surrogate or placeholder for another object to control access to it. This can be useful for various purposes, such as lazy initialization, access control, monitoring, and logging. Let’s create an example of the Proxy pattern in C# with a use case of an Image proxy that loads images on-demand.
Create the Subject Interface:
Define an interface that represents the object you want to create a proxy for.
public interface IImage
{
void Display();
}
Create the RealObject (Real Image):
This is the class that represents the real object, which might be expensive to create.
public class RealImage : IImage
{
private string filename;
public RealImage(string filename)
{
this.filename = filename;
LoadImageFromDisk();
}
private void LoadImageFromDisk()
{
Console.WriteLine("Loading image from disk: " + filename);
}
public void Display()
{
Console.WriteLine("Displaying image: " + filename);
}
}
Create the Proxy:
The Proxy class implements the same interface as the Real Object and acts as a placeholder, delegating work to the Real Object as necessary.
public class ImageProxy : IImage
{
private RealImage realImage;
private string filename;
public ImageProxy(string filename)
{
this.filename = filename;
}
public void Display()
{
if (realImage == null)
{
realImage = new RealImage(filename);
}
realImage.Display();
}
}
Use Case – Lazy Image Loading:
In this use case, we’ll use the Proxy pattern to load images on-demand to save resources. RealImage objects are only created when necessary.
class Program
{
static void Main(string[] args)
{
// Create an ImageProxy
IImage image = new ImageProxy("sample.jpg");
// Image is not loaded until Display is called
image.Display();
// The second call to Display doesn't reload the image
image.Display();
}
}
In this example, we have an ImageProxy
that stands in for the real image (RealImage
). When the Display
method is called on the proxy, it creates the real image if it hasn’t been created yet. This lazy loading behavior is particularly useful when dealing with resource-intensive operations or objects that you want to load only when necessary.
The Proxy pattern is also useful for scenarios like access control, logging, and monitoring, where you can control access to the real object and perform additional actions before or after delegating to the real object.