The Observer Pattern is like a DMV wait line. Event Listeners are more like a fire truck with its sirens blaring. Let me explain, and give you an example of each — the former in Ruby, and the latter in JavaScript.
Many people introduced to Observer Pattern will find that it is very similar to Event Listeners. Both have objects, “observers” and “listeners”, that are waiting for something to notify them before they can do their thing.
However, while some use cases of Event Listeners may follow the Observer Pattern, not every implementation of Event Listeners fits in the Observer Pattern. A general difference between the two is that observers are watching something specific, while listeners are not.
More specifically:
Observers are registered to the subjects they are observing, and a subject knows all the observers it notifies. The subject explicitly notifies each of its observers when there is an event.
Listeners, on the other hand, are listening for events on a global Events instance. They are not paying attention to any one subject, but instead are listening for a global Events
broadcast that an event has happened. Any objects that are triggering events will broadcast their events without knowing who they are broadcasting to.
Let’s look at some examples!
Observer Pattern
The Observer Pattern is like a DMV wait line. You show up at the DMV and register with them for a wait number. The DMV is the subject, when you register to get your wait number the DMV adds you to its list of observers. Everyone waiting at the DMV is an observer and is notified when a new wait number is called to the window.
Here’s the scenario in (ruby) code. We have our Subject and Observer classes:
# Subject
class DMV
def initialize
@observers = []
end
def add(observer)
@observers << observer
end
def remove(observer)
@observer.delete(observer)
end
def notify
@observers.each do |observer|
observer.update
end
end
end
#Observer
class Driver
attr_reader :name
def initialize(name)
@name = name
end
def update
puts "#{name} has been alerted"
end
end
You can register instances of a Driver
to an instance of a DMV
:
oakland_dmv = DMV.new
freddie = Driver.new("Freddie")
brian = Driver.new("Brian")
oakland_dmv.add(freddie)
oakland_dmv.add(brian)
berkeley_dmv = DMV.new
roger = Driver.new("Roger")
john = Driver.new("John")
berkeley_dmv.add(roger)
berkeley_dmv.add(john)
And now whenever an instance of DMV has a state change, you can call notify()
which will call update()
on all the observers.
oakland_dmv.notify()
> "Freddie has been alerted"
> "Brian as been alerted"
berkeley_dmv.notify()
> "Roger has been alerted"
> "John has been alerted"
As you can see, each instance of a DMV
only notifies observers that were registered to them.
You can pass data from the Subject to the Observers via notify()
and update()
. To learn more about the different ways to pass data with the Observer Pattern, checkout Intro to Observer Pattern.
Event Listeners
A common form of Event Listeners we see are JavaScript’s event listeners, which are more like a fire truck with its sirens blaring. The fire truck doesn’t know who is listening, but will sound its sirens to broadcast to anyone who is listening that this event is happening. People who are driving along the road (ostensibly) know how to respond when they hear sirens, but they aren’t specifically waiting for a siren to sound off as they are commuting to work.
Again, let’s take a look at a code example, this time in JavaScript:
class FireTruck {
turnOnSirens() {
const sirensBlaring = new Event("sirensBlaring");
document.dispatchEvent(sirensBlaring);
}
}
class Driver {
constructor() {
document.addEventListener("sirensBlaring", this.pullOver);
}
pullOver() {
console.log("safely pull over");
}
}
As you can see in the example above, the FireTruck
doesn’t need to keep track of who is listening for its event. In fact, there could be multiple instances of FireTruck
and every instance of Driver
would be able to respond to "sirensBlaring"
. On the other hand, in the Observer Pattern example above, you can have multiple instances of DMV
and they would each have their own list of Observers.
One thought on “Did You Hear Something? Observer Pattern vs. Event Listeners”