“This is the 11th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge.”

Introduction to the chain of Responsibility pattern

The chain of responsibility pattern is a behavioral design pattern that allows you to send requests along the handler chain. After receiving a request, each handler can either process the request or pass it on to the next handler on the chain.

At the heart of the chain of responsibility pattern is the resolution of sequential execution processes within a set of services.

The chain of responsibility pattern makes the individual service modules clearer, and each module can be acquired through next. Each next is implemented by an inherited unified abstract class, and eventually all class responsibilities can be dynamically choreographed, and the choreography process can be made configurable.

When using the chain of responsibility, if the scenario is relatively fixed, you can write it to the code to initialize it. However, if the business scenario changes frequently, it can be processed as AN XML configuration or saved to the database for initialization.

In actual business, a series of packaging will be carried out when the chain of responsibility is used. By assembling different responsibility nodes, a complete chain of responsibility is formed.

The chain of responsibility pattern handles the single responsibility and the open closed principle well. Simple coupling also makes the object relationship clearer, and external callers do not need to relate how the chain of responsibility is handled.

Chain of responsibility pattern structure

  • handler

A common interface for all concrete handlers is declared, which usually contains only a single method for request processing, but sometimes includes a method for setting handlers up and down the chain.

  • Base handler

Is an optional class where you can place sample code shared by all handlers. Typically, this class defines a member variable that holds a reference to the next handler. A client can create a chain by placing a handler’s constructor or setting method. The class can also implement the default processing behavior, determining that the next handler exists before passing the request to it.

  • Specific handler

Contains the actual code to process the request. After each handler receives the request, it must decide whether to process it or whether to pass the request along the chain.

  • The client

Chains can be generated once or dynamically according to program logic.

Applicable scenario

  • When the program needs to handle different kinds of requests in different ways, and the request type and order are unknown in advance.
  • When the business logic must execute multiple processors in sequence.
  • Handlers and their order must be changed at run time, using the chain of responsibility pattern.

implementation

  • A signature that declares the handler interface and describes the request handling method
  • An abstract handler base class can be created based on the handler interface (a member variable is required to store references to the next handler in the chain)
  • Create a concrete handler subclass and implement its handler methods. After receiving a request, each handler must make two decisions: 1. Whether to process the request itself; 2. 2. Whether to pass the request down the chain.
  • The client can assemble the chain itself or obtain a preassembled chain from another object.
  • The client can trigger any handler in the chain, not just the first. The request goes through the chain until one of the handlers refuses to continue or the request reaches the end of the chain.

Demo

The chain of responsibility pattern is unusual in C# programs because it only works when code is dealing with a chain of objects.

Handler interface

// </summary> public interface IHandler {IHandler SetNext(IHandler handler); object Handle(object request); }Copy the code

An abstract class

/// </summary> public abstract class AbstractHandler :IHandler {private IHandler _nextHandler; public IHandler SetNext(IHandler handler) { this._nextHandler = handler; return handler; } /// <summary> /// </summary> /// <param name="request"></param> /// <returns></returns> public virtual object Handle(object request) {  if (this._nextHandler ! =null) { return this._nextHandler.Handle(request); } else { return null; }}}Copy the code

Implementing abstract classes

/// </summary> public class MonkeyHandler: AbstractHandler {public Override object Handle(object request) {if ((request as string)==" monkey. ") {return "In the monkey class "+ request.toString (); } else { return base.Handle(request); Public class SquirreHandler -- SquirreHandler -- SquirreHandler -- SquirreHandler -- SquirreHandler -- SquirreHandler -- SquirreHandler -- SquirreHandler Abstract {public Override object Handle(object request) {if ((request as string) == "squirrel ") {return" in squirrel "+ request.ToString(); } else { return base.Handle(request); // </summary> </summary> public class DogHandler: AbstractHandler {public Override object Handle(object request) {if ((request as string) == "puppy ") {return" In puppy "+ request.ToString(); } else { return base.Handle(request); // The Handle method in the superclass}}}Copy the code

Client and Main() validation

class Client { public static void ClientCode(AbstractHandler handler) { foreach (var item in new A List < string > {" squirrel ", "monkey", "people"}) {Console. WriteLine (" who is: "+ item). var result = handler.Handle(item); if (result! =null) {console. WriteLine(" who: "+result); } else { Console.WriteLine("No Find"); }} console. WriteLine(" start "); } } class Program { static void Main(string[] args) { var monkey = new MonkeyHandler(); var squirrel = new SquirreHandler(); var dog = new DogHandler(); monkey.SetNext(squirrel).SetNext(dog); // Build the chain console. WriteLine("---------- for the first time "); Client.ClientCode(monkey); Console.WriteLine(); Console.WriteLine(" second time "); Client.ClientCode(squirrel); Console.WriteLine(" the third time "); Client.ClientCode(dog); Console.ReadKey(); }}Copy the code

You can see the value of the output in red in the picture above, the first time (initial position) is not executed at the end of the dog, the second time (middle position) is not executed at the monkey, and the third time is not executed at all (third time to the end of the chain).

Small remarks

Life is short, I don’t want to pursue what I can’t see, I just want to grasp what I can see.

I am A hui, thank you for reading, if it is helpful to you, please click like, forward thank you.