Chain of Responsibility – It lets the program passes the client requests along a chain of handlers. Upon receiving the client’s requests, each handler will decide to process the client’s requests or give them to the next handler in the chains.

From Design Pattern – Behavioral Patterns

Structure

Chain of Responsibility pattern – Class diagram UML

Applicability

  • Using the responsibility pattern chain is when the programs are expected to process different requests in various ways. However, the exact types of requests and their sequences are unknown beforehand.
  • Using its is when it’s essential to execute several handles in a particular order.
  • Using the CoR pattern is when the set of handlers and their order are supposed to change at runtime.

Pros and Cons

PROS

  • The programs control the request order handling.
  • Single Responsibility Principle – The programs can decouple classes which invoke operations from classes that perform operations.
  • Open-closed principle – The programs can control new handlers into the object without breaking the existing client code.

CONS

  • Some requests may end up unhandled.

How to Implement

#1 Basic Sample

class Program
{   
	static void Main(string[] args)
	{
		var monkey = new MonkeyHandler();
		var squirrel = new SquirrelHandler();
		var dog = new DogHandler();

		monkey.SetNext(squirrel).SetNext(dog);

		AbstractHandler handler = squirrel;

		foreach (var food in new List<string> { "Nut", "Banana", "Cup of coffee" })
		{
			Console.WriteLine($"Client: Who wants a {food}?");

			var result = handler.Handle(food);

			if (result != null)
			{
				Console.Write($"   {result}");
			}
			else
			{
				Console.WriteLine($"   {food} was left untouched.");
			}
		}


		Console.ReadKey();
	}

	public interface IHandler
	{
		IHandler SetNext(IHandler handler);

		object Handle(object request);
	}

	public abstract class AbstractHandler : IHandler
	{
		private IHandler _nextHandler;

		public IHandler SetNext(IHandler handler)
		{
			this._nextHandler = handler;

			return handler;
		}

		public virtual object Handle(object request)
		{
			if (this._nextHandler != null)
			{
				return this._nextHandler.Handle(request);
			}
			else
				return null;
		}
	}

	public class MonkeyHandler : AbstractHandler
	{
		public override object Handle(object request)
		{
			if ((request as string) == "Banana")
				return $"Monkey: I'll eat the {request.ToString()}.\n";
			else
				return base.Handle(request);
		}
	}

	public class SquirrelHandler : AbstractHandler
	{
		public override object Handle(object request)
		{
			if(request.ToString() == "Nut")
				return $"Squirrel: I'll eat the {request.ToString()}.\n";
			else 
				return base.Handle(request);
		}
	}

	public class DogHandler : AbstractHandler
	{
		public override object Handle(object request)
		{
			if(request.ToString() == "MeatBall")
				return $"Dog: I'll eat the {request.ToString()}.\n";
			else
				return base.Handle(request);
		}
	}
}

#2 Web Application Project

Step 1 Create the handler interface and the CofR interface in the Core project.

Fig 1 Chain of responsibility pattern solution explorer
Fig 2 IHandler interface file source code
Fig 3 ICofR interface file source code

Step 2 Create a AbstractHandler class file, a HandlerServices class file, the IDHandler class file and the FindHandler class files in the Core project’s service folder.

The AbstractHandler class inherits the handler interface and statement the private interface variable.

Fig 4 AbstractHandler class file source code

The IDHandler class file and the FindHandler class file inherits the abstract class of the AbstractHandler file.

Fig 5 IDHandler class file source code
Fig 6 Findler class file source code

Step 3 The HandlerService class file inherits ICofR interface class, then adding the businesses logic in its.

Fig 7 HandlerService class source code

Step 4 Create the chain of responsibility pattern controller file and page files in the web project.

Step 5 Register the interface class and service class in the scoped service which puts on the Startup.cs file.

services.AddScoped(typeof(ICofR), typeof(HandlerService));

Fig 8 Chain of responsibility pattern result

Reference

1 Comment

Leave a Reply