The Chain of Responsibility (CoR) design pattern is used when you need a request handled by the most appropriate object for the request. You don’t need to worry about which object handles the request or even if they’ll handle it the same all the time. For example, suppose you have a constantly changing marketplace and the specs of your request change as well. Rather than building an application that links a specific request to a specific request handler the CoR pattern decouples the two so that when a request is sent, all you know is that the most appropriate object will handle it. Our department buys USB drives in bulk from China. In the request for the drives I put in a set of criteria and send the request to my Chinese buyer. He is instructed to get the lowest price for the drives as long as they meet the specs in the required bulk. Now I don’t know which manufacturer will win the contract (which object will handle the request), but since I trust my agent in China, I am confident he’ll get the best price even though the price will vary depending on everything from the dollar’s exchange rate with China to the availability of USB drives. Because so many variables change, I need the flexibility that changes with both the request and the request handler. That’s something like the way the CoR design pattern works—it takes a request and finds the most appropriate way to handle it.
Play the application to see what happens (not much) and download the code using the following buttons:
Chain of Responsibility Overview
Because looking at a Class Diagram is useful for seeing the larger context of the design pattern, we’ll look at it first and then go about describing its features.
This looks fairly simple, and at the basic level it really is. Like some of the other design patterns, the Client is part of the pattern, and so it’s integral. At the center of the pattern is the Handler interface. For the time being, think of the interface as an abstract class because that is what is used in the initial example. The abstract class includes a function for setting successors in a chain and another to handle a request. Finally, the ConcreteHandler classes represent the specific and different classes that handle requests. Generally speaking, an application would include several ConcreteHandler classes, and each is set up in a chain to deal with requests where appropriate.
Unchain My Request
In their work, the Gang of Four, illustrate the CoR using a Help desk. The Help desk is set up in a hierarchy with different Help topics. As a request moves through the hierarchy it attempts to find the concrete handler that deals with its query. Another good example (my favorite) is provided by the Freemans in their Head First Design Patterns book. Their example envisions a company that gets different kinds of email, and to sort it out, the CoR design pattern is used. It has separate handlers (ConcreteHandler) for fan mail, spam, complains and so forth. So, when an email arrives, it is automatically handled in the appropriate manner moving it along a chain. Both of these examples share the concept of uncoupling the request from the handler. In this way, both requests and handlers can be changed without disrupting the larger program. As anyone who has worked with a program to handle products or services in a rapidly changing environment knows, your design needs this kind of flexibility.
Figure 2 provides a general idea of a chain of concrete handlers set up in succession. When the request comes in, it is examined by ConcreteHandler A. If A cannot handle the request, it is passed on to ConcreteHandle B and so forth until it either runs out of concrete handlers or is handled. The different colored diamonds represent the different ways of handling a request. The process terminates once the request is handled.
Figure 2: Request Chain
If you want some kind of handler to deal with unhandled requests, the last concrete handler in the chain (ConcreteHandler E in Figure 2) could be a residual one that issues a notice informing the user that the request could not be handled. However, the alternative of simply not handling a request because the criteria for handling is not in the chain of concrete handlers is perfectly acceptale.
The Implicit Receiver
One of the two key concepts in the CoR pattern is implicit receiver. Even though the requesting object may not have any idea of which concrete handler will handle a request, the one that actually handles it is the implicit receiver. That clears up a lot of possible confusion. Given the criteria of the request, only one of the concrete handlers can meet that criteria, and so implicitly that is the receiver. It’s a simple concept but one that you need to keep in mind.
Because the request is uncoupled from the receiver, you can easily add more concrete classes to be the implicit receiver. Imagine a business with a CoR that finds items in certain price ranges. Let’s say that a merchant finds that most people will spend $50 on a project. He has handlers for under $50 and from $50 to $100. Research shows that most of the under $50 sales are actually for around $20. To increase revenue, he adds a new concrete handler that offers a $35 to $65 range. Because he used a CoR design pattern, all he needs to do is to add a handler for that range and make minor adjustments to the concrete handlers below and above that range. Because the receivers are implicit and uncoupled from the request, such adjustments are easy and the program can be changed without having to refactor the entire application.
The Successor
The second key concept in the CoR is successor. To move a request along a chain and to keep the receiver implicit, each object must maintain a common interface. The successor defines a way to move along the chain of objects and shares the same interface as do the receiver objects (concrete classes). As a result, the pattern requires some method for specifying successors in the interface but must hold the interface. In the class diagram in Figure 2, you can see the successor in the Handler interface looping back to itself.
One way of setting up this method can be seen in the interface itself. A successor object is typed as the interface (Handler). Then the method parametizes the successor object. The following snippet shows how this looks:
... abstract public function handleRequest($request); abstract public function setSuccessor($nextService); ... |
Each of the concrete handlers includes a way to pass on the request to the next concrete handler using the successor object .
A Simple PHP Chain of Command Application
In coming up with an application, I envisioned a request-for-information page where the user could select from one of three radio buttons. Depending on the selection, the Chain of Responsibility would send the request to be handled by the appropriate concrete handler. (It “handles” it by sending a message to the screen, but it could do anything you want.)
The client sends out a request with request implied by the selection of the radio button. It begins with a query for “Information” and works up the chain until he finds a match to the originating query. It’s a simple application, but one where you can see all of the parts working together. The application has the following components:
- Handler class that acts as an interface for the application
- Three concrete handler classes that act as receivers
- A Client class that makes the request
- A request that calls the Client
Handler Class
This first class acts as an interface. It is an abstract class and for the purposes of design patterns, abstract classes and interfaces are often referred to a interfaces. In the Gang of Four’s book, a reference to an interface generally means any class from which concrete classes derive with the emphasis on the set of methods held in the interface whether it is a PHP interface structure or an abstract class.
abstract class Handler
{
abstract public function handleRequest($request);
abstract public function setSuccessor($nextService);
}
?>
|
As you can see, the Handler class has two methods. The first method will be used to set the successor and the second method to handle requests. However, because the request handler involves different requirements for each concrete handler, the method remains abstract in the Handler class.
Concrete Handler Classes
Because the Handler class is an abstract one, all of the subclasses provide concrete methods in the Handler class. The HandleRequest( ) method needs to communicate the limits of its ability to handle the request and pass on to its successor if it cannot handle it. The following three concrete handlers do that:
//Information.php class Information extends Handler { private $successor; public function setSuccessor($nextService) { $this->successor=$nextService; } public function handleRequest ($request) { if ($request->getService() == "Information Design") { echo ("All types of information can be easily stored " . " |
The concrete handlers evaluate the weight of the request. The chain of responsibility begins with the Information class. If it cannot handle the request, it passes it on to its successor, the Services class. If the Services class cannot handle it, it is passed on to the Product class which will handle it. In this particular example, we will be using radio buttons to make the request, and so we can be assured that if a request is made (a radio button is selected), it will be handled. In some cases a Chain of Responsibility may be given a request that cannot be handled. In such cases, the developer has the choice of sending the user a message indicating that the request cannot be handled or do nothing.
Request and Client Classes
The Client class implements the request and establishes the hierarchy in the chain of responsibility. The Request class is simply a way of encapsulating the request, which is nothing more than getter/setter methods. The getter and setter methods are set up and the value for a load is paramaritized in the main method.
//Request.php class Request { private $value; public function __construct($service) { $this->value=$service; } public function getService() { return $this->value; } } ?> |
You will notice that all of the concrete handlers hold a reference to the Request class. In effect it is a mixin class used by both the Client class and ConcreteHandler classes. However, it is only instantiated by the Client class. As noted, though, it encapsulates the request following good OOP practices.
//Client.as class Client { public function __construct($queryNow) { $Info = new Information(); $CodeSer = new Services(); $Product = new Software(); $Info->setSuccessor($CodeSer); $CodeSer->setSuccessor($Product); // Generate and process load requests $loadup = new Request($queryNow); $Info->handleRequest ($loadup); } } ?> |
In looking at the Client class, all of the request objects are instantiated and then the successors are set. Three different request values should test each of the three concrete classes’ ability to recognize itself as the implicit receiver. The Client begins each request with the object that is at the beginning of the chain of responsibility.
Finally, you will need a set of operations to launch the Client. Here’s what we used:
//TestCoR.php ini_set("display_errors","2"); ERROR_REPORTING(E_ALL); include_once('Client.php'); include_once('Handler.php'); include_once('Request.php'); include_once('Services.php'); include_once('Software.php'); include_once('Information.php'); if (isset($_POST['sendNow'])) { $queryNow = $_POST['query']; } $makeRequest = new Client($queryNow); ?> |
Many PHP programs use far fewer files for such small project as we use here. However, the separate files for classes and interfaces promotes the idea loose coupling. It makes it easy to change because you know that no more than a single class is in each file. When it comes time to change, you can switch out the parts like boxcars on a train. Each is an encapsulated operation that has a single responsibility. Some you will re-use, others will be changed and still others will be removed. All this can be done without the program crashing.
A standard HTML program provides the UI for the user to make a request.
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<style type="text/css">
body
{
background-color:#FFCC33;
color:#0e6829;
font-family:Verdana, Arial, Helvetica, sans-serif;
font-size:10px;
}
style>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Customer Querytitle>
head>
<body>
<img src="logo/LogoMoon.png" />
<form action="TestCoR.php" method="post">
Select the service that will help you or your company.<br/>
<p/>
<input type="radio" name="query" value="Software Security" />
Software Security<br/>
<input type="radio" name="query" value="MySQL Database Design" />
MySQL Database Design<br/>
<input type="radio" name="query" value="Information Design" />
Information Design<br/>
<p/>
<input type="submit" name="sendNow" value="Click here to send information to Sandlight" />
form>
<p/> *Sandlight shares this information with no one.<br/>
We're as paranoid as you are.
|