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

3.3 The Observer Pattern

Similar to pub/sub, the Observer pattern allows us to observe an object, and react when it changes. Frameworks such as KnockoutJS take observing to the maximum, but we can use a much simpler implementation to facilitate communication between different entities in our applications.

3.3 The Observer Pattern

Hi folks. In this lesson we're going to take a look at the observer pattern. The observer pattern is very closely related to the pubsub pattern that we looked at earlier in the course. In fact, some people assert that the pubsub pattern is simply an implementation of the observer. There is a subtle difference between the two however. While the pubsub pattern implements a global message buster, any object can pass or receive messages through. The observer is more specific and requires that observers to subscribe directly to the object firing the event. The observer pattern is another pattern which promotes loose coupling between the various components of our application. And is very commonly seen in Java Scripts. So let's create a simple implementation of the Observer Pattern. We'll need an object known as the subject, which is the object that other modules observe and we'll need at least one observer. It's the subject's responsibility to maintain the list of observers, and also to provide an API that allows the observers to observe the subject, or stop observing, and to notify the observers when a change in state occurs. The observer list can be an entity in its own right that handles adding and removing observers to the list, and retrieves the list of observers. Let's add a new file for this module first of all. Let's call this one observers.js. The constructor for this can be super simple. We set a single property called observers and initialize it with an empty array. The method to add new observers is also very simple. The method receives the observer as an argument, and pushes it into the observer's array. The method to remove the observer is a little larger but it's still pretty simple. This method receives the observer to remove as an argument. We can use JavaScript's filter array method to test each observer in the array. The filter method doesn't alter the array it's called on but it does return a new array so we can set the new array as the value of the old array. The callback function passed to the filter method will be passed the current observer and is invoked for each observer in the array. This method should return true if the current item should be included in the returned array, or false if it shouldn't. So in this case, when the observer does match the observer to be removed, the filter method will return false, and the observer to remove will not be included in the returned array. We just need to add one more method now and that's the method to obtain the list of observers. This is also very simple. We can just return the array of observers. Lastly this module will also need to return its constructor. So now let's add the subject module. We can create a new file in the observer directory called subject.js. We'll need to use the require function in this module. And we'll use that to load the observer's module that we just created. And it's returning a constructor, so we capitalize the name of the variable. So now let's add a constructor for the subjects. Again it's gonna be very simple. In this example, the subject can be based on an array, and we'll notify observers whenever an item is added or removed from the array. The subject will maintain its list of observers, so we add a property equal to observers, which is a new instance of the observers' entity that we just created. The array being observed is added as a property coup collection, and again, is initialized as an MT array. So now let's add some methods to our subject, starting with the method used to add new observers. The observe method receives the observer to add and just passes this through to the observer's add method. The method to remove observers is equally as simple. Again what we do is pass through the observer that gets passed to the method, to the remove method of the observer's module. The last method to do with observing is the notify method. The notify method receives the event and some data to pass through to the observers. Inside the method, we first need to get the list of observers. We don't strictly need to expose a get method from the collection of observers, but doing so is cleaner, because otherwise at this point we would have to type something like this instead And that just looks a bit rubbish, doesn't it? So let's get rid of that. That's why we're using a get method. And because that returns an array, we can just chain the for each method directly onto that. So the callback function in this case will be passed to each observer from the array of observers. And inside the callback we can just use the notify method and pass through the name of the event and the data. So lastly we can answer methods to add or remove items from the collection. The add method receives the items to add to the array. It pushes the new item into the array and then invokes it's own notify method specifying the event name as added and passing through the item that was added to the collection. The subject's remove method is very similar to the observer's remove method. This method receives the item to remove and again it uses the filter method to overwrite the collection array. Instead of just returning we can use an if statement and return true if the item is not the item to remove. If it is the item to remove, we can use the notify method once again. But this time we specify the name of the event as removed and pass through the item BeingRemoved before returning false. The filter method can accept the object used as this inside the call back function passed to the filter method. And we need to use it this time to be able to invoke this .notify. Lastly our subject can return it's constructor as well. So now let's add a simple observer class so that we can easily create new observers. The constructor for an individual observer will accept a name property so that we know which observer is which. Observers will also need a notify method. And let's just keep things simple and log some stuff to the console, like the name of the event, the data that was passed to it, and the observers' name. And lastly, let's just return the constructor to keep things consistent. So now we should have all the pieces in place. Let's add the init module for this example. First of all, we need to add a few variables. And we can then load the observer and subject modules. And now let's new up a subject and a couple of observers. And now let's add some data objects to pass into the collection being observed. >> Now, let's add our observers to the subject's observer collection. We can then add our data to the subject's collection. At this point, let's update the main file so that we can run the example now. And let's head back to the browser and just see if everything's wired up correctly. Okay. So we are seeing several different console logs here. We're seeing two console logs from the first observer and two console logs from the second observer. So the event is coming through as undefined for some reason. Let's just figure out what's happening there. And it's because I'm trying to read the name of the event. But there is no name. The event is the name. So now let's have one of our observers stop observing the subject. And we do that with the unobserve method. And let's pass through the first observer. And now let's remove some data from the collection. And this time, only Observer 2 is still observing the array. So only this observer sees the removed event. So in this lesson we looked at the observer pattern, which is very similar conceptually to the pubsub pattern that we looked at earlier in the course. This pattern differs in that the observers are coupled to the subject, but not all coupling is bad. Some level of coupling is usually required in an application for the application to function. And the main thing to avoid is unnecessary, unintentional, or excessive coupling. Thanks for watching.

Back to the top