Chain of Responsibility
- You use this pattern when you need a pipeline or chain of objects for processing the request
Classical Structure
Scenario
- Build a web server that process the request
Problem
- Webserver is tightly coupled with authentication
- Order of action is hardcoded in the class
internal class Authenticator
{
public bool Authenticate(HttpRequest request)
{
Console.WriteLine("Authenticating request");
return request.Username == "admin" && request.Password == "admin";
}
}
internal class Compressor
{
public void Compress(HttpRequest request)
{
Console.WriteLine("Compress request");
}
}
internal class Logger
{
public void Log(HttpRequest request)
{
Console.WriteLine("Logging request");
}
}
internal class HttpRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
internal class Webserver
{
public void Handle()
{
//Authenticate
var authenticator = new Authenticator();
authenticator.Authenticate(new HttpRequest { Username = "admin", Password = "admin" });
//Log
//Compress
}
}
Solution
internal class HttpRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
internal abstract class Handler
{
private Handler next;
protected Handler(Handler next)
{
this.next = next;
}
public void Handle(HttpRequest request)
{
if (DoHandle(request))
return;
if(next != null)
next.Handle(request);
}
protected abstract bool DoHandle(HttpRequest request);
}
internal class Authenticator : Handler
{
public Authenticator(Handler next) : base(next)
{
}
protected override bool DoHandle(HttpRequest request)
{
Console.WriteLine("Authenticating request");
return !(request.Username == "admin" && request.Password == "admin");
}
}
internal class Compressor : Handler
{
public Compressor(Handler next) : base(next)
{
}
public void Compress(HttpRequest request)
{
Console.WriteLine("Compress request");
}
protected override bool DoHandle(HttpRequest request)
{
Console.WriteLine("Compressing");
return false;
}
}
internal class Logger: Handler
{
public Logger(Handler next) : base(next)
{
}
protected override bool DoHandle(HttpRequest request)
{
Console.WriteLine("Logging request");
return false;
}
}
internal class Webserver
{
private Handler handler;
public Webserver(Handler handler)
{
this.handler = handler;
}
public void Handle(HttpRequest request)
{
handler.Handle(request);
}
}
public class Program
{
static void Main(string[] args)
{
var compressor = new Compressor(null);
var logger = new Logger(compressor);
var authenticator = new Authenticator(logger);
var webserver = new Webserver(authenticator);
webserver.Handle(new HttpRequest { Username = "admin", Password = "admin123"});
}
}
Example Structure
Example Code