design pattern

Behavioral Design Patterns: Chain of Responsibility

Today we’ll begin the last leg of our journey through all the most common design patterns within our Guide to Software Design Patterns series. It’s finally time to move onto Behavioral patterns, which try to build a foundation on which objects can communicate and assign responsibilities to one another. First up in the Behavioral pattern list is the Chain of Responsibility design pattern, which makes it easy to chain objects together in an ordered set. A specific, logical requirement is passed into the chain and is checked against each object in the set, in order, until a suitable match is found that meets the needs of the particular requirement.

In this article we’ll explore the chain of responsibility design pattern in more detail, looking at both a real world example and a fully-functional C# code sample that will illustrate how you might use the pattern in your own code, so let’s get going!

In the Real World

Upon hearing the term chain of responsibility, it isn’t a far stretch to think of the similar phrase known as a chain of command. In point of fact, both terms are often used interchangeably to mean the same thing. However, when dealing with programming, the concept of command isn’t always applicable (or, more likely, could be confused for its other meanings), so the chain of responsibility pattern was born and is generally more representative of the intended goals.

That said, one obvious real world example of a chain of responsibility pattern is the order of command in a governmental or business organization. For example, The United States Presidency is held by the current President, but an extensive line of succession is laid out through the United States Constitution and the Presidential Succession Act of 1947. In the event that the current President cannot continue with his or her responsibilities, the Presidency would pass down to the Vice President, then the Speaker of the House of Representatives, and so forth.

While a chain of succession begins from the top of the chain and works its way downward, a chain of responsibility typically works its way upward, starting from the bottom. This practice is commonly seen in the realm of business, when an important decision must be made within a company. The decision must pass up the chain of command, from employee to supervisors to manager to president and so on, until an individual with enough authority to make an appropriate decision is found.

How It Works In Code

We’ll be basing our code sample off the real world chain of responsibility pattern found in many companies and put into practice via its employees. Specifically, imagine we starting a publishing company and we have a series of books we want to publish. Each book is assigned a type of cover (paperback, digital, or hard cover), along with an estimated publishing cost. We’ll then create a series of specifications (using the specifications pattern) that will define various criteria to check for our books, such as their cover type or publication cost. We’ll create a list of employees with varying authority levels (CEO, President, CFO, etc), and assign each employee a set of specifications that will determine what types of books that employee is qualified to approve for publication. Finally, with everything in place, we can loop through each book and run up the chain of responsibility of each employee, checking whether he or she has the proper authority to publish that book. If so, publication occurs, and if not, the next employee up the chain is checked for authority.

That’s the basic explanation of what our code accomplishes. As usual, we’ll start with the full code sample below, and then we’ll dive into the details and explain what’s going on afterward:

Note: As you can see, this code sample is quite massive and somewhat complex. As such, to save space in this article, we’ve excluded the code of the Logging class that is used to output information to the console. Feel free to check out previous design pattern articles, such as our Proxy Design Pattern article, if you need that code. Otherwise, this sample will work perfectly fine by replacing all Logging.Log() method calls with Console.WriteLine() calls instead.

The chain of responsibility design pattern consists of just two fundamental objects:

  • Handler Interface – Defines the methods and properties that will be used to handle requests.
  • ConcreteHandler Class – Handles all requests and stores a successor. If the current ConcreteHandler can manage a request, it does so, otherwise it passes it along up the chain to the successor.

For our purposes, we’ve defined the IEmployee interface to behave as the Handler interface, along with the Employee class, which implements IEmployee and acts as our ConcreteHandler:

For now let’s ignore the IPublishable interface, which Employee requires its Type to be a member of, and just briefly explain what the class does. The fundamental requirement is the storage of a successor, which is an IEmployee<T> instance itself. This will be used to indicate which other Employee is next in the chain of responsibility. We also have a few properties like name and position that we’re using for logic and output elsewhere, to make it easier to differentiate between employees.

Beyond that, our basic logic occurs in CanApprove(T book) and PublishBook(T book). When we want to publish a passed book we first need to check if the current Employee has the authority to approve that request, so CanApprove(T book) calls the _specification.IsSatisfiedBy(T book) method. We’ll explore what this does later, but the purpose here is to check if the current Employee meets all the specification criteria required by the book in question. If so, we Invoke() the _publicationAction that was passed and output the successful publication result. On the other hand, if CanApprove(T book) is false, we check if _successor exists, and if so, we call PublishBook(T book) for the successor (the next Employee up the chain of responsibility). This process repeats until an Employee with the proper specifications necessary to publish the book are found, or until the end of the chain is reached and publication, therefore, fails.

Our Book class implements the IPublishable interface, which we saw used earlier by the Employee class, and simply covers the fundamental properties of a book (title, author, cover type, and publication cost):

The last set of classes we’ll need for our setup is the ISpecification<T> interface, and the Specification<T> class that implements it. As previously mentioned, we’re using the specification pattern here, so that we can define loose sets of business rules for our books, which can then be freely applied to our various employees based on their ranks. To that end, the fundamental behavior of the specification pattern is the IsSatisfiedBy(T expression) method, which basically checks if a passed in candidate or expression meets the criteria of (is satisfied by) the current specification. IsSatisfiedBy(T expression) returns a boolean indicating the success or failure of this check.

Beyond that we also have a few extensions for the Specification<T> class, so we can perform simple And, Or, or Not logic using multiple specifications:

Whew! Now that everything is setup we can make use of our chain of responsibility pattern and test it out. There’s a lot going on in our Main(string[] args) method, so we’ll break it down into smaller chunks.

We start by creating a new List<Book> and add a handful of books, each with a title, author, cover type, and estimated publication cost. Our goal is to check this set of books, to see which ones can be published, and which Employee within our chain of responsibility has the authority to do so:

Next we need to create some specifications. These can be as simple or as complex as we want. In this case, we start by creating a specification for each CoverType of book that we have. We also create some PublicationCost-based specifications, which each cover a unique range of costs:

Now we need to create a few Employees, which will serve as the basis of our chain of responsibility. To better differentiate between each employee we assign them a unique Name and Position. Lastly, we’ve created a new PublicationProcess instance, which is a simple class that implements two methods, PublishBook(Book book) and FailedPublication(Book book). These two methods will be passed to our various Employee instances to indicate the behavior (the publication Action<T>) that should be taken when the Employee successfully publishes (or fails to publish) a book:

Now that our employees are defines we want to start giving them each various levels of responsibility and authority. We accomplish this by assigning them sets of specifications. The comments provide details on what is going on in each example, but the basic goal is to ensure that a particular Employee can only handle certain types of books, based on CoverType and/or PublicationCost:

Now that each Employee has their own set of specifications, the last step is to create the chain of responsibility. We do this by calling SetSuccessor() for each Employee, to indicate which other Employee is his or her immediate superior. We’ve used defaultEmployee throughout this to be the baseline or “fallback” Employee instance. The Action<T> that was passed to defaultEmployee during instantiation was publicationProcess.FailedPublication. This action allows us to specify that, should a particular book reach the defaultEmployee in the chain (above the CEO), that indicates that no actual employee met the criteria of the book, so publication is not possible:

With everything ready to go, we begin the process of searching up through the chain of responsibility for an applicable Employee that has the authority to publish each Book, starting at the bottom with the director:

The end result of all this after running our code is some output showing us which books in our set were actually published, and by whom:

For each Book in the set we can actually look back at the specifications assigned to each Employee in the chain to see why that Employee had the authority to approve publication. In the case of 1984 by George Orwell, no Employee was found that met those specifications. We can see it’s a paperback CoverType and at $22,500 would fall into the lowBudgetSpec. However, looking back at our Employee specifications we can see that none of them meet both those criteria. The director meets the lowBudgetSpec, but only for books that are digital CoverType. As a result, our defaultEmployee ended up being the only candidate, which forced a call to FailedPublication(), hence the output that we see.

This is a small taste of what the chain of responsibility design pattern is capable of. It can be quite useful in certain situations, and when combined with other patterns like the specification pattern used above, it can be both powerful and robust. For more information on all the other popular design patterns, take a look at our ongoing design pattern series over here!