Proxy
The proxy pattern
The proxy pattern is a structural pattern and is exactly what the pattern name states a proxy. The idea being if you need to proxy an object, say it uses a lot of resources, such as an image, file or remote call, you can use the proxy to allow access to the object's parameters and delay the larger call to process the resource unless necessary. A little like 'lazy loading', also to note is the proxy pattern is similar to the decorator pattern with both using the same interface but it's not used to add functionality but to prevent or delay functionality.After that confusing statement lets show the proxy structure:
Doesn't really show much, so lets show some code:
abstract class Subject {
protected string bigResource;
public Subject(string bigResource) {
this.bigResource = bigResource;
}
public void InformationToConsole() {
Console.WriteLine($"The resource is {bigResource}.");
}
public abstract void Request();
}
Our abstract class above just takes the name/location of a resource and stores it. It
also provides some information about the resource in the method
InformationToConsole().protected string bigResource;
public Subject(string bigResource) {
this.bigResource = bigResource;
}
public void InformationToConsole() {
Console.WriteLine($"The resource is {bigResource}.");
}
public abstract void Request();
}
We implement our class and want to load the resource immediately:
class BigResourceEater : Subject {
public BigResourceEater(string bigResource) : base(bigResource){
Request();
}
public override void Request() {
Console.Write("\r\nRequesting huge resource");
// simulate handling large resource
for (int i = 0; i < 5; i++) {
Console.Write(".");
Thread.Sleep(1000);
}
Console.WriteLine($"\r\nThe huge resource is loaded {this.bigResource}.");
}
}
To avoid the large resource, maybe just to get information about the resource, we make a proxy:
public BigResourceEater(string bigResource) : base(bigResource){
Request();
}
public override void Request() {
Console.Write("\r\nRequesting huge resource");
// simulate handling large resource
for (int i = 0; i < 5; i++) {
Console.Write(".");
Thread.Sleep(1000);
}
Console.WriteLine($"\r\nThe huge resource is loaded {this.bigResource}.");
}
}
class BigResourceEaterProxy : Subject {
BigResourceEater bigResourceEater;
public BigResourceEaterProxy(string bigResource) : base(bigResource){
// Request(); this is missing as we don't want to load the huge resource
}
public override void Request() {
if (bigResourceEater == null) {
bigResourceEater = new BigResourceEater(bigResource); // arghhh no DI!!!!
}
bigResourceEater.Request();
}
}
To test the code above:
BigResourceEater bigResourceEater;
public BigResourceEaterProxy(string bigResource) : base(bigResource){
// Request(); this is missing as we don't want to load the huge resource
}
public override void Request() {
if (bigResourceEater == null) {
bigResourceEater = new BigResourceEater(bigResource); // arghhh no DI!!!!
}
bigResourceEater.Request();
}
}
static void Main(string[] args) {
// we just want the information
Subject bigResourceEater = new BigResourceEater("AVeryBigResource.com");
bigResourceEater.InformationToConsole();
Subject bigResourceEaterProxy = new BigResourceEaterProxy("AVeryBigResourceWithProxy.com");
bigResourceEaterProxy.InformationToConsole();
Console.ReadKey();
}
The output to the console is:
// we just want the information
Subject bigResourceEater = new BigResourceEater("AVeryBigResource.com");
bigResourceEater.InformationToConsole();
Subject bigResourceEaterProxy = new BigResourceEaterProxy("AVeryBigResourceWithProxy.com");
bigResourceEaterProxy.InformationToConsole();
Console.ReadKey();
}
Requesting huge resource.....
The huge resource is loaded AVeryBigResource.com.
The resource is AVeryBigResource.com.
The resource is AVeryBigResourceWithProxy.com.
The huge resource is loaded AVeryBigResource.com.
The resource is AVeryBigResource.com.
The resource is AVeryBigResourceWithProxy.com.
Summary
The proxy pattern is another pattern where I found it difficult to not produce a convoluted example, especially since we now have Asynchronous Programming, but I think the pattern is valid.