What is common between a washing machine that has just completed washing and your employee who tells you that she is done creating the annual reports? They are both using the observer design pattern.
The observer pattern in real life
Using a washing machine works like so. You set up the machine to do the laundry. When the machine is done, it sounds a buzzer. Other appliances like the microwave oven or a toaster work the same way. Your smartphone does the same thing. Only, it notifies too much!
Delegation of work to people works the same way. Efficient delegates will come back to you after they are done. Without them notifying you, you would never know if the work is done.
Without observer pattern
What if your delegate doesn’t let you know when the task is done? There are two ways for you to know.
- One is to estimate the time it would take for the task to complete and check the status after the estimated time is up. Let’s call this the check-after-estimated-time method.
- Another way is to frequently check with the delegate at short intervals. Let’s call this the check-progress method. Let’s apply the two methods on devices which don’t care to notify us.
How neither method works well
Certain models of domestic electronic RO (Reverse Osmosis) water purifying dispensers take ages to start after you press the start button. They have such a thin spout that it takes 90 seconds to fill a 1-litre water bottle. Given the startup time and the time to fill up a litre of water, it takes 2 to 3 minutes to operate the machine to go from an empty bottle to a full one. If you have a 2-litre bottle, then the wait isn’t pleasant.
2 to 3 minutes are too long to wait by the side of the dispenser. You could focus on other things meanwhile. But what if you focus on your work so hard that you forget about the bottle. If you don’t turn the dispenser off, it will keep dispensing water. The bottle will overflow and you’ll have water all over the counter.
Alternatively, you keep checking the progress at short intervals, thus constantly interrupting your deep focus task. A good example is pasteurising refrigerated milk over a gas stove. Since boiled milk rises fast, it could spill over and create a mess in your kitchen. So you need to keep checking the milk at intervals of a minute, watching it turn from cold to lukewarm, lukewarm to warm, warm to hot and hot to smoking hot. When the milk froths as it nears a boil, you need to stay near the stove to make sure the milk doesn’t spill.
Gadgets with observer pattern
But here is how some manufacturers have used the observer pattern to safely stop the device’s task after completion and notify you when they are done. Some water dispensers have a dedicated 1-litre button that dispenses exactly a litre of water. After 1 litre is dispensed, they stop the water flow and sound a beep. You get to keep your empty bottle under the dispenser’s spout and go back to your work.
An electric induction stove slowly boils milk for 20 minutes at alternating high and low temperatures and then turns itself off with a beep. The milk is perfectly boiled at the end and stays within the vessel. There’s no spillage.
So, what’s the observer pattern?
Let’s use a domestic bread toaster as an example as we describe the observer pattern.
- You put slices of bread into the slots on the toaster and press the button that starts the process. You are the delegator. The toaster is the delegate. The process of toasting has been delegated to the toaster.
- Next, someone wants to know when toasting is done. This someone is the observer. The observer is notified by the delegate after the process is done. E.g. the toaster pops the bread out and pings. Usually, the delegator itself is the observer. E.g. You yourself respond to the toaster’s ping and take the bread out.
- Alternatively, what if you are making toast for your grandmother who doesn’t know how to operate the toaster? You switch on the toaster and tell granny to use a pair of tongs to take the hot toast out carefully, only after she hears a ping. After setting the toaster, you walk away for your other tasks of the day. Granny hears the ping and retrieves the fresh warm toast. Here, you are the delegator and the toaster remains the delegate. But grandma is the observer since she is the one who listens for and responds to the ping.
- The delegate and observer have a set of events which are agreed upon. This agreement is represented by an interface in object-oriented programming. See the post on an introduction to object-oriented programming to learn what interfaces are. In our example, the toaster agrees to ping for anyone who wants to listen. We represent that with the onToastDone method within ToastListener interface.
- The observer wants to know when the delegate’s process is done. It adds itself as a listener to the delegate. By agreement, the delegate promises to call the interface method on the listener. Since you have told grandma to listen for a ping, you have added her as a listener for the event when the toast is done. When the toast is done, grandma is able to hear the ping. This can be represented as the toaster calling the onToastDone method on grandma since she is the ToastListener.
- Neither the delegator (you) nor the observer (grandma) has to keep observing the progress of the delegate (toaster). Both of you are free to walk away and mind your own tasks. It is the delegate’s responsibility to notify when done, but you still have to listen.
Observer pattern in software
The speed at which data is read from a hard disk or from the Internet is much slower than the speed of a computer’s processor. The observer pattern is used to good effect here.
In every modern programming language, calls to load files from the hard disk and Internet use the observer pattern. Your program will request the hard disk or the network for a file but move on to the instruction. The hard disk or the network operation will let the app know that the requested resource is loaded and ready for use.
What would happen if instead of using the observer pattern, your app were to wait for the hard disk or Internet to finish its job before moving on? You would have an ugly, unresponsive app that fails to respond to your clicks and taps.
Delegation and observation help us focus on tasks that are important to us. They help us move on from time-consuming tasks and start the next one, keeping our day active. Without the observer pattern, we’d have a world where everyone waits for devices and delegates to complete a delegated task, without being able to focus on their own tasks.