If you have ever visited a government office, you are probably directed from one counter to another to get tasks done. Why doesn’t the same person do everything? This is because the work is divided into small tasks and each government official is given the responsibility of only one task. Once done, that official will direct you to the next one. You are seeing the chain of responsibility design pattern in action.
Chain of responsibility in real life
Let’s consider a quiz game in which the man in charge asks a question and allows teams A, B, C and D to take turns one after another to answer the question. Let’s assume that the man points to team A first. If they know the answer, they will speak it out and grab the points. However, if they do not know the answer, they are allowed to say, “Pass”. The question then passes to team B.
A team that cannot answer the question passes that question to the next team. The team that answers the question bags the points and no further teams are involved in that question.
There are two ways for a question to terminate and for the next question to be presented. The first is when one of the teams answers the question. Points are awarded and the game moves on. The second is when none of the teams is unable to answer the question. The question is discarded, no points are awarded and the game moves on.
So, what is chain or responsibility?
A chain of responsibility pattern is a pattern where a request object passes through a chain of handler objects. A handler object heads the chain and gets the chance to handle the request first. If it cannot, then it passes the request to the next handler in the chain. The next handler is called the successor. As long as handlers are unable to handle the request, they will pass it on to the successor. The request terminates in one of the two ways. First, a handler knows how to process the request and fulfill it. A fulfilled request does not proceed to other handlers. Second, if none of the handlers can fulfill the request, then the request is discarded.
In the quiz example above, the question is the request. The participants of the quiz are the handlers.
Also note that the all handlers are derived from a blueprint — an interface. If you want to learn about interfaces and other basics of object oriented programming, please check the post: Introduction to object-oriented software. The object which sends the request only needs to remember that the blueprint has a method to pass the request to a handler.
Chain of responsibility in software
Mouse click handling is the best example for the chain of responsibility pattern. Let’s consider a web page where a button is placed inside a form, which in turn is inside the browser window. Let’s say the user clicks on the screen. Typically a screen is divided into a grid of pixels and the user clicks on one of those.
After the pixel is clicked, the operating system gets the UI widget that encloses the smallest area around the clicked pixel. In our case, if the user clicks inside the button. Initially the operating system cannot distinguish between buttons, images or screens. It simply knows that a pixel on the screen is clicked. But while processing the click, it deduces that the button is the smallest area that encloses the pixel. So the click event is passed to the button. If the programmer of the web page has meant for the button to do something when it is clicked, then the button grabs the event and does its processing. The click is fulfilled. However, what if the button is not programmed to handle the click? What if the widget is not a button, but simply a text label or an image? In that case, the widget does not handle the click and passes it on to the next widget up the chain, which is typically the next biggest enclosing area around the clicked pixel, i.e. the form. The event passes from the form to the web page to the browser window itself. If any of the components in between handles the click event, then the event is fulfilled, else it is discarded as an unexpected click and an unactionable click from the user.
Software, as in real life, often needs to achieve complex goals. To keep software maintainable, it is broken into several components, each responsible for a task. Often, a request lands up in the hands of a component that accepts requests, but is not directly responsible for fulfilling it. The chain or responsibility pattern makes sure that your software components are each nimble with single responsibilities, but that they can talk to each other and get the work done.