Chain Of Responsibility Design Pattern Using C#

Introduction

Chain of responsibility (COR) decouples the sender of the request and its receiver. Now you must be wondering same one can achieve using Command Pattern also. But with COR, the request is transferred to another object making them part of the chain. Each object can handle the command or forward it when it cannot handle the command on its own. The object does not have to know the chain’s structure and it can keep direct reference to its members.

Definition from GOF

Avoid coupling the sender of the request to its receiver by giving more than once object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it (GOF, Gamma et. al).

With this pattern, chain of objects examines a request. As shown in the block diagram below, each object in turn examines the request and handles it, or passes it on to the next object in the chain.

Every Request has an implicit Receiver

The first object in the chain receives the request and either handles it or forwards it to the next candidate on the chain. The object that made the request has no explicit knowledge who will handle it i.e. every request has got an implicit receiver.

To forward the request along the chain, and to ensure receivers remain implicit, each object on the chain shares a common interface for handling requests and for accessing its successor on the chain.



Figure 1: Cliet

Example

Let’s consider an example,

A chain of garments stores are interconnected. As on when a customer orders an item and store manager finds that it is not available in the local store. The local store requests the availability of the item (with Size, age, Male / Female type, color etc.) from other stores in the chain. Whoever has it, responds to the sender’s request. In this way, sender of the request has no explicit knowledge about the exact handler of the request. The sender object just forwards the request along the chain.

UML Diagram


Participants: Players in this pattern are shown below with respect to their mapping to the example presented.

Handler: Abstract class(CheckItemInStoreChain)
  • Defines an abstract class for handling the request.
  • Implements the link to successor (the next in the chain).

ConcreteHandler (StoreLocal, StoreOtherCity)

  • Handle requests it is responsible for.
  • If the ConcreteHandler can handle the request, it does so; otherwise it forwards the request to its successor.

Client

  • Initiates the request to a ConcreteHandler object on the chain.

Class Diagram of the example



Figure 2:
Diagram

In the diagram shown above, CheckItemInStoreChain is an abstract class. The abstract class is extended by each store. Each Local store has a reference object to keep track of the successor in the chain. This successor object would eventually take care of the request if the requester can’t handle it on its own.

Collaboration Diagram

Client issues a request (e.g. checking for an item), the request gets transferred along the chain (e.g. from first concrete handler in the chain to second concrete handler) until a ConcreteHandler object takes responsibility for handling it.

So as to summarize, COR offers the idea of loose coupling by forming a tree of responsible objects. An object has to know that a request will be handled “appropriately” without knowing who handled the request. This approach has at times disadvantage when chain of objects is not configured properly. As mentioned, a request does not has an explicit receiver; the request can go unhandled down the tree of responsible objects if no object takes the responsibility of handling it.