Thursday, September 10, 2009

Decorator Pattern with C#

Decorator Pattern classified into Structural Pattern which add responsibilities to objects dynamically.

A client application often needs to augment the services provided by methods of some class, by inserting some pre and post-processing tasks before and after the method calls. If distinct pre and post-processing tasks were to be carried out for different clients, the application logic would become complex by conditional statements, leading to a maintenance nightmare.

Consider a class where clients can invoke method to transfer files to and from some remote server. In addition to being able to upload and download files, the client application would also like to log all file transfer requests and perform access checks for each invocation.

An implementation based on the Decorator pattern would derive a class from FileTransfer and override the virtual methods, inserting the additional operations before and after calling the base methods. Client still continue to call the same method; however additional responsibility is added to the class without affecting other clients using the same functionality. Thus, Decorator Pattern allows dynamic and transparent addition and removal of responsibilities without affecting client code.

FileTransfer Class (used by multiple clients):
namespace MyProject.DecoratorPattern
{
public class FileTransfer
{
public virtual bool UploadFile(string url)
{
bool result;
// File Upload Logic
Console.WriteLine("File Uploaded to url :" + url);
result = true;
return result;
}

public virtual bool DownloadFile(string url, string localpath)
{
bool result;
// File Download Logic
Console.WriteLine("File downloaded to '{0}' from url '{1}'", url, localpath);
result = true;
return result;
}
}
}



Derive from FileTransfer Class:
namespace MyProject.DecoratorPattern
{
class Decorator : FileTransfer
{
//Additional Responsibility added without affecting client code, demonstrate Decorator Pattern.
public override bool UploadFile(string url)
{
bool result = false;
if (!AccessAllowed(url)) return result;
result = base.UploadFile(url);
LogActivity(url);
return result;
}
//Additional Responsibility added without affecting client code, demonstrate Decorator Pattern.
public override bool DownloadFile(string url, string localpath)
{
bool result = false;
if (!AccessAllowed(url)) return result;
result = base.DownloadFile(url, localpath);
LogActivity(url);
return result;
}
private bool AccessAllowed(string url)
{
bool result;
// URL access Logic
Console.WriteLine("Access Allowed to url :" + url);
result = true;
return result;
}
private void LogActivity(string url)
{
// Logic to Log Upload/Download Activity
Console.WriteLine("Activity logged for url: " + url);
}
}
}


< Back to Design Patterns

1 comment: