Chain of Responsibility Pattern

author-image
CIOL Bureau
Updated On
New Update

Avijeet Dash & Satyabrata Dash

Intent

Avoid coupling the sender of a request to its receiver by giving more than
one object, a chance to handle the request. Chain the receiving objects and pass
on the request along the chain until an object handles it.

In 30 Seconds

The catch in this pattern is "it lets you send requests to an object
implicitly through a chain of candidate objects". Any Candidate object
might fulfill the request depending on the run time conditions. The number of
candidates is open-ended and you can select which candidates participate in the
chain at run time.

The Chain is generally achieved by using inheritance to form a tree structure
of all the candidate objects from very specific types at leaf nodes to very
general one at root level. An example of this pattern: In Java1.0 the
event-handling model was based on this pattern.

All the GUI elements capable of generating an event (e.g. MouseClick,
MouseMove etc) were from the parent class Component. Any event not handled by
(for instance) a button would automatically be fired to the next level of
container and this continues recursively until it’s handled or ignored in the
whole chain of candidate GUI objects. This model has the drawbacks of making the
system slow and has lesser flexibility. It is slow because an event used to
traverse the whole chain of containers until gets handled. It is less flexible
as every event handling GUI element has to inherit from Component. In Java 1.1
and Java2 the event model was changed to ‘Observer Pattern’ where only
objects interested in an event gets the event when they register a listener for
it.

Motivation

One better example of this pattern is a ‘context-sensitive help system’.
Say you have two buttons in a Print dialog, a Print button and an Ok Button. The
Print Dialog is in an application window.

Now when you need help information on the print button and no specific
information exists, it should show the help information of the immediate context
that’s of the dialog box. So basically the help information is organized in
such a ‘more specific’ to ‘more general’ way that always the immediate
context can handle the request or forward it to a higher level object.

  1. So the Client that issued the request has no direct reference or explicit
    knowledge of the object that ultimately handles the request.
  2. Each object in the chain shares a common interface for handling requests
    and for accessing its successor on the chain.
Advertisment

Generally this pattern is used in conjunction with Composite. Composite
builds the chain using inheritance. So the default successor is the parent
class. All of them in the hierarchy support a handleRequest() method. If any
child node doesn’t want to handle the request in a specific way and doesn’t
override handleRequest() then, when a request comes due to inheritance
handleRequest() of the parent class gets executed.

Structure

Context-Sensitive Help System

Click here to view image

Chain Of Responsibility UML diagram

Click here to view image

 Sample Code

/* This is the abstract Handler code */

package chainexample;

import java.lang.*;

public abstract class MyHandler extends java.lang.Object

/** successor is a private variable to hold the next in line for the

Chain of Responsibility

*/

private MyHandler successor = null;



/** integer value of the request that this instance is responsible

for

*/

public int myRequest = 0;



/** The Handler Method is the constructor for the class Handler.

This method constructs a new instance of class Handler and initializes

the successor for this instance to the next instance to be called in

the Chain of Responsibility

@param s This parameter is used to hold the next Handler in the

Chain of Responsibility

@param r This parameter isused to identify which request the instance

will take responsibility for

*/



public void MyHandler(MyHandler s, int r)

{

successor = s; // set successor for this instance to be the

// instance of MyHandler passed in.

myRequest = r; // set the request that this instance is responsible for



}//EndofConstructor MyHandler





/** The MyHandler Method is the default constructor for the class MyHandler.

This method constructs a new instance of class MyHandler and initializes

the successor for this instance to the next instance to be called in

the Chain of Responsibility. In this case there is no parameter accepted

so the defined constructor above is called with a parameter of 'null'

as the next MyHandler in the Chain.

*/



public void MyHandler()

{

this.MyHandler(null,0); // call the defined constructor with a null
instance.

}//EndofConstructor MyHandler





/**

SetSuccessor is a method offered to enable the client to set the

next MyHandler in the Chain.

@param h is of type MyHandler and should be the next Hanlder to call in

the chain if the HandleRequest does not fulfill the request.

*/

public void SetSuccessor(MyHandler h)

{

Advertisment

successor = h;

}//EndofMethod SetSuccessor







/**

HandleRequest is the method that should be called to process or deal

with the responsibility requested. The implementation provided in the

abstract class is a default method offered in the case where the

a subclass does not override this method to provide a concrete

HandleRequest. Note that the specific instance of MyHandle can override

the semantics by returning a unique value for string.



@exception NoSuccessor This exception is raised when the instance of the

MyHandler class has no successor. No attempt is made to determine whether a

successor ever existed for this instance.

@param request This parameter represents a set of requests that the

instance could handle or process. This parameter can and is expected to be

modified to represent the type of request that the instance can handle.

@return String This method returns a text String.



*/

public String HandleRequest(int request) throws NoSuccessor

{

String returnValue = "";



if (successor == null){

throw new NoSuccessor("No successor");

} else {

returnValue = successor.HandleRequest(request);

}



return returnValue ;

}//EndofMethod HandleRequest

}//EndofClass MyHandler

/* This is a Concrete Handler */

package chainexample;





public class RequestHandler extends MyHandler

{

String instanceName = "Not set";



public RequestHandler(String name, RequestHandler s, int r){

Advertisment

super.MyHandler(s, r);

instanceName = name;

}



public RequestHandler(String name){

super();

instanceName = name;

}



public String HandleRequest(int request) throws NoSuccessor

{

String returnValue = "";

if (request == this.myRequest) {

returnValue = "Handled by " + this.instanceName;

}

else {

try {

return super.HandleRequest(request);

}

catch (NoSuccessor e) {

returnValue = "No Successor Exception Caught by " +this.instanceName;

}

}

return returnValue;

}// EndOfMethod HandleRequest

}//EndOfClass RequestHandler

 

Complexities simplified

Implementing the Successor Chain

The successor link can be either a new link or an existing link. An existing
link is the case of the parent class in a part-whole hierarchy. This is simple
and saves space as well. If the tree structure doesn’t reflect the chain of
responsibility, the application needs then different successor links can be
defined.

Representing the Request

The common implementation of handleRequest() would be to call a specific
method i.e. the request is a hard-coded method invocation. To support an
open-ended set of requests the handler function can take in a request code (an
integer or string constant) and dispatch them to appropriate methods. Even
better way to handle the request is to make it an object.

Advertisment

Related Patterns

Chain of responsibility is often applied in conjunction with Composite.

tech-news