ActionScript 3.0 Chain of Responsibility Design Pattern: Decoupling Request and Request Handler

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 Flash 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 Flash 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.

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.

Figure 1: Chain of Responsibility Class Diagram

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:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
public class Handler
        {
                protected var successor:Handler;
 
                public function SetSuccessor (successor:Handler):void
                {
                        this.successor=successor;
                }
….

Each of the concrete handlers includes a way to pass on the request to the next concrete handler using the successor object .

A Minimalist Chain of Command Application

In coming up with an application, I envisioned a building contractor who needed to haul different loads to a job site. In order to save money, he wanted to use a pickup truck that would best haul a given load but no more. In that way, he would not waste money on both gas and trucks that hauled greater loads that might be needed elsewhere.

The client sends out a request with a certain load weight, and the CoR picks out the best truck for the job. It begins with the smallest truck and works up the chain until he finds a truck that optimally handles the required load. 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 class that encapsulates the request

Handler Class
This first class acts as an interface. It is an abstract class in spirit (since ActionScript 3.0 and ECMAScript r4 have no real abstract class.)

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package 
{
	//Abstract class
 
	public class Handler
	{
		protected var successor:Handler;
 
		public function SetSuccessor (successor:Handler):void
		{
			this.successor=successor;
		}
 
		public function HandleRequest (request:Request):void
		{
			//Provide details in subclasses
		}
	}
}

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 must override the 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:

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
//GMC.as 
package 
{
	// "ConcreteHandler" 
 
	public class GMC extends Handler
	{
		override public function HandleRequest (request:Request):void
		{
			if (request.Pounds < 1547.0)
			{
				trace ("A GMC Canyon would be good for this. Weight: "+request.Pounds);
			}
			else if (successor != null)
			{
				successor.HandleRequest (request);
 
			}
		}
	}
}
 
//Dodge.as
package 
{
	// "ConcreteHandler" 
 
	public class Dodge extends Handler
	{
		override public function HandleRequest (request:Request):void
		{
			if (request.Pounds < 1750.0)
			{
				trace ("Dodge Dakota can handle this load. Weight: "+ request.Pounds);
			}
			else if (successor != null)
			{
				successor.HandleRequest (request);
 
			}
		}
	}
}
 
//Ford.as
package 
{
	// "ConcreteHandler" 
 
	public class Ford extends Handler
	{
		override public function HandleRequest (request:Request):void
		{
			if (request.Pounds < 1890)
			{
				trace ("This load required a Ford 150. Weight: "+request.Pounds);
			}
			else if (successor != null)
			{
				successor.HandleRequest (request);
			}
		}
	}
}

The concrete handlers evaluate the weight of the request. If the request is within the range of the limit, the request is handled, but if not, the request is sent to a successor, if any. In this particular implementation of the CoR, if the weight is over 1889, the request is not handled.

Request and Client Classes

The Client class implements the request and establishes the hierarchy in the chain of command. The Request class is simply a way of encapsulating the request, which is nothing more than a number. The getter and setter methods are set up and the value for a load is paramaritized in the main method.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Request.as
package 
{
	// Request details 
 
	public class Request
	{
		private var loadWeight:Number;
 
		// Constructor 
		public function Request (loadWeight:Number)
		{
			this.loadWeight=loadWeight;
		}
 
		// Getters and Setters 
		public function get Pounds ():Number
		{
			return loadWeight;
		}
		public function set Pounds (loadWeight:Number):void
		{
			loadWeight=loadWeight;
		}
	}
}

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. If you feel queasy about using the Request class, you can easily change the ConcreteHandler classes to accept what amounts to a numeric literal. Then, each HandleRequest would simply accept a literal value directly rather than using the Request class.

?View Code ACTIONSCRIPT
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Client.as
package 
{
	import flash.display.Sprite;
	// This is the Client
 
	public class Client extends Sprite
	{
		private var Acme:Handler;
		private var Paramount:Handler;
		private var Pinacle:Handler;
		private var loadup:Request;
 
		public function Client()
		{
			// Setup Chain of Responsibility 
			Acme = new GMC();
			Paramount = new Dodge();
			Pinacle = new Ford();
			Acme.SetSuccessor (Paramount);
			Paramount.SetSuccessor (Pinacle);
 
			// Generate and process load requests 
			loadup = new Request(1200);
			Acme.HandleRequest (loadup);
 
			loadup = new Request(1650);
			Acme.HandleRequest (loadup);
 
			loadup = new Request(1795);
			Acme.HandleRequest (loadup);
		}
	}
}

In looking at the Client class, all of the request objects are typed as the interface—Handler rather than to a concrete class. Then, each instantiates a concrete handler, and sets up the succession. Three different request values should test each of the three concrete classes’ ability to recognize itself as the implicit receiver.

The Client also begins each request with the object that is at the beginning of the chain of responsibility. The smallest load is handled by the GMC class, and so the instance of that class (Acme) is always used to send out a request.

When you test the program, you will get the following output:

A GMC Canyon would be good for this. Weight: 1200
Dodge Dakota can handle this load. Weight: 1650
This load required a Ford 150. Weight: 1795

Each of the three requests was handled by the appropriate concrete handler. Even better, if new kinds of requirements or requests are brought in, the changes are only in the concrete handlers.

Reader Challenge

As usual I’d like any feedback as far as improving the application, but more importantly, I’d like to see three added concrete handler classes. Here’s what they are:

  • A lower base weight of 500 pounds for a mini-pickup.
  • A mid-size weight that can be inserted between the Dodge and the Ford
  • A class that would respond to the fact that the load weight they requested is too big for any of the available trucks.

If the CoR design pattern has the kind of flexibility advertised, this ought to be a snap.

  • Share/Bookmark

Related posts:

  1. PHP Chain of Responsibility Design Pattern from ActionScript 3.0
  2. Guest Post: Pieter Grobler- Understanding Design Patterns through Science Fiction
  3. ActionScript Proxy Design Pattern : The Virtual Proxy (A Minimal Abstract Example)

5 Responses to “ActionScript 3.0 Chain of Responsibility Design Pattern: Decoupling Request and Request Handler”


  • This is a great explanation. Well done!
    The handlers remind me of a singly-linked list, and the request class makes me think of a value object. Perhaps you could employ a linked list where each node held a reference to a handler that could be applied to the request.
    In this way, you could insert of remove handlers from the chain of responsibility at runtime. (Of course, you could add such functionality to the handler superclass as well. I think either would be good solutions yes?)
    -t.

  • Hi Timbot,

    Thanks man. I’m trying not to go off half-cocked on these new (to me) DPs.

    When working on CoR, I kept thinking that there’s a lot of different ways that this can be done, and my solution is only one of many. Chandima and I welcome lots of different ideas, and if you could generate a sample CoR with your idea, we could put it up for discussion.

    Also, I think it would be helpful to work with requests that involved different kinds of request objects. Numeric requests are pretty simple (that’s why I used one!) and I don’t think it’d be too difficult to cook up something interesting if any readers here would be interested in playing around with some ideas.

    Bill

  • I imagine this kind of thing being very useful in an assets managing class. Various classes in your project may want to load assets, but the assets they load are all different (and at times they may not even know the kind of asset they are loading – if they are receiving the asset url from a proxy class that loaded an external xml, for example). So the client would make a request for the asset, and the asset managing class would pass the request to different handlers (eg. JPEGHandler, SWFHandler, FontHandler, XMLHandler etc.) until the asset is loaded correctly and then passed back to the client.

    The difficulty I foresee would be how to effectively manage the communication between the parties, as event dispatching could be tricky. Does this make sense, and do you have any suggestions on how that communication would run?

  • Hi Rigard,

    That is a very interesting idea. You would effectively use the CoR pattern as a filter (well, let’s face it; that’s what it is) to load assets with different properties. The filtering effect would determine what kind of loading and display methods you would use. Wow! I really like that idea.

    Thank you very much,
    Bill

  • A really awesome [thing] about this design is that your concrete handlers don’t have to be final. I used this in a program using different notification types, but some notifications needed to trigger multiple actions. So what I did was make a CoR and passing the notification event through the entire chain, each handler triggering if the notification type matched. This made a great reusable mechanism, because it’s really easy to implement new handlers and a user-based config, allowing users to disable certain triggers (just leave them out of the chain :D)

Leave a Reply