I’ve been trying to get my head around the observer pattern. Every time I read an article or see a video tutorial it seemed easy.
Can you check if what I have done is in fact the observer pattern? Here’s the code in codesandbox
I created a very basic shopping card thing with three classes: Store, Products, Cart - where the Store is the observer. I pass the Store to the other two and let them push/register observer methods, and also let them trigger them all.
In my head the Store should be publishing something and the other two classes should be listening, whereas what this code is doing is taking requests!
It’s like if you are a radio station DJ and I give you a CD and tell you “when I notify you, play the CD”
Whereas I thought it was the other way around. You, the Store DJ play whatever song, and I’ll start dancing at home if you happen to play my favorite song
If someone could glance at this basic codesandbox just to let me know if I got it right.
Are you just trying to learn the pattern? If so, a shopping cart is not the best way to wrap your head around it.
Assuming you are just wanting to learn the pattern, I would suggest you use something closer to a real life publisher/subscriber model such as a Newspaper or Magazine Distributor.
I will use my real life Sirius Radio subscription as an example. In my car radio I have set favorite songs/artists (I subscribed, I am the observer). When Sirius Radio (publisher) is going to play (publish) one of my “favorites” I am notified on the screen so I can change to the channel to hear it. Same thing happens for every other person that has subscribed to Sirius Radio and whose favorite songs/artists are about to play which may or may not be the same as mine.
All of us subscribers can also unsubscribe at any time, either from the favorites or the service completely.
Going back to your cart example, does it really make sense to pass a store to a cart? When you go to the grocery store do you pass the store to your buggy/shopping cart or do you pass your groceries to the store for checkout?
const observer = new Store();
const cart = new Cart({ observer });
I would start with a generic implementation instead of a concrete one such as a shopping cart. This should make it easier for you to “get your head around” the pattern.
<script>
class Subject {
constructor () {
this.criticalNumber = 0
this.observers = []
}
addObserver (observer) {
this.observers.push(observer)
}
removeObserver (observer) {
let index = this.observers.findIndex(o => o === observer)
if (index !== -1) {
this.observers.splice(index, 1)
}
}
notify () {
console.log('Notifying observers about some important information')
this.observers.forEach (observer => {
observer.update(this.criticalNumber)
})
}
changeCriticalNumber () {
/* Changing the critical information */
this.criticalNumber = 42
/* Notifying the observers about this change */
this.notify()
}
}
class Observer {
constructor (id) {
this.id = id
}
update (criticalNumber) {
console.log(`Observer ${this.id} - Received an update from the subject ${criticalNumber}`)
}
}
let s = new Subject()
s.addObserver(new Observer(1))
s.addObserver(new Observer(2))
/* Changing the critical information */
s.changeCriticalNumber()
</script>