Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Js design 1
  • Overview
  • Transcript

3.4 The Chain of Responsibility Pattern

Does your application have input that should be handled in a different way depending on the type of the input? The Chain of Responsibility pattern can free us from the anti-pattern of gigantic if...else conditional blocks. To start, the input is passed to the first handle. Can the first handler handle the data? If not, then pass the data to the next handler, and so on.

3.4 The Chain of Responsibility Pattern

Hi folks, in this lesson we're gonna look at the chain of responsibility pattern. This pattern features a request sender and a series of one or more request handlers that form a chain. The request sender passes a request, or command, to the first handler in the chain. And if this handler can't do anything with it, it passes to the next handler in the chain. And so on and so forth until the request has either been handled or has reached the end of the chain. Another variation of this pattern is where all of the handler's process or handle the request in some way before passing it on to the the next handler in the chain. The purpose of this pattern is to decouple the request sender from the request handler. This pattern isn't the most commonly seen pattern in JavaScript, but it's great fun to code and can be considered a good exercise in object oriented JavaScript. In the example for this lesson, we can have a communication object that represents a specific type of communication, like a text message, an email, etc. We can then have a series of handlers that each know how to deal with one type of communication. So let's make a start. We can create a new directory called cor. And inside this directory, let's add a new module called handler.js. This will be the base class of the individual handlers. Let's add a simple constructor first. The constructor will accept potentially three arguments. The first two are required and are the type of communications so that the handler will know if it can handle it or not, and the actual handler itself which will process the communication. The third optional argument is the next handler in the chain, if there is one. And we can just set these arguments as properties of the handler object. Now let's add a handle request method to the prototype that all handlers will inherit. Inside this method we'll first need to check whether the communication type matches the communication type property of the handler. This will tell the handler whether or not it can handle the request. If the handler can't handle the communication type, we then need to determine whether there is a next handler in the chain or not, and react appropriately. This time we use JavaScript's ternary operator to see if this .next handler is not 4C. If it's not, we can invoke the handle communication method of the next handler and pass it the communication. If it is 4C, we can just log to the console to say that the type of the communication could not be handled and then return. If the handler can handle the communication type, we can just pass the communication type to the handler. And lastly, this module can just return the constructor. Great, so now we need a series of handlers. Let's create a new directory inside the cor directory and call it handlers. Inside this folder we can add the different handlers. Let's start with an email handler. We'll use the require function to load the base handler. And we can create the email handler by creating a new instance of the base handler class. So the email handler has a type of email, and the handler is going to be a function called handle email, which we'll add in just a moment. And the email handler will be the last handler in the chain, so the next handler is set to null. So now let's add the handle email function. And to handle the email we can just do a simple console log. And last of all the module can just return the created email handler. So this time we're returning an instance of the email handler, we're not returning the constructor. We could also add a text message handler. And this will look very similar to the email handler So this time we require in the email handler as well as the base handler class, and when we create the SMS handler using the new handler constructor, we pass the email handler as the next handler. So this is how the chain of handlers is formed. This time we have a handle SMS function and that just handles the SMS message in the appropriate way, which in our case is just by logging into the console. So let's also add a call handler. So now let's use the init module for this example to create some communication objects and pass them along the chain. First of all, we can create some variables. We can load the base handler class in order to start up the chain, and we need to load the first handler which in this case is the cor handler. In a real application, the first handler in the chain would probably be the one most frequently used. So now let's add some communications. Just setting example properties here. Neither of these phone numbers are supposed to be real phone numbers, and if they are real phone numbers, I do apologize to the person that owns those numbers. Please don't be tempted to call them. Okay great, so to set up a chain we can create an instance of a handler which has no type and no handler. We just specify the first handler in the chain by passing it as the third argument to the constructor. So now we can start the process of handling a request, and to do that we use the handler's handle request method. So we just need to update the main.js file to load the files for this example. And let's go to the browser now and see if our chain is working. So it looks like require can't find our SMS handler, and that's because we've called it text message. Let's just rename that to the simpler SMS. And let's go back and try again. So it's saying that handleCall is not defined and that's happening in the file callda JS@98. So let's see what's happening. And it's because we've used a function expression instead of a function declaration. So let's try that once again. So we have another error now. And it's saying that this.nexthandler.handlecommunication is not a function. So let's try and debug what's happening. And the method is actually handlerequest, instead of handlecommunication. So let's update handlerequest to be handlecommunication, which I think is probably a more descriptive method name. Okay, lets go back and try again. So we've got the same error here. And this time it probably should work. Yeah, so this time the email is now being handled, and as you can see, it's being handled by the email handler. And let's try handling some other types of communication. And as you can see, we see the appropriate messages, so we know that the chain is functioning as it should and each handler is only handling the types of communication that it knows how to handle. This makes it really, really easy to add new handlers because each handler is only coupled to one other handler and the client is only coupled to the first handler. The chain itself is pretty resilient because if we start to use a new type of communication which we don't have a handler for, we shouldn't see any errors. Let's just go back and try that. So now we have a telepathy object. We don't have a handler for this type of communication, but let's pass it to our chain anyway. And all that happens is we see the default message that the communication type, ESP, could not be handled. So in this lesson we looked at the chain of responsibility handler. We learned that this pattern is useful when we have a variety of different types of objects that all need to be handled in a unique way. We saw that the pattern is great for loose coupling and makes extending the system with new handlers extremely easy. Thanks for watching.

Back to the top
Continue watching with Elements