level up your Object Oriented JS with behavioral patterns(object communication)
Tags: javascript, webdev, oop
Published: 2021-09-12 00:50:07



Behavioral  patterns - facilitate object communication


object communication is a vital piece in OOP, encapsulating data and functionality is the first step, communication is the most crucial step, a program is made up of smaller programs which are objects, communication knits everything together to a full functional system


## Observer pattern 
 A subject(object) maintains a list of its dependents(observers) and notifies them when state changes;

its one to many relationship, single object being observed for changes by multiple objects 


```python

// pseudo 
  Object subject:
     list -> subscribers
	 state -> {}
	 
	 
	 subscribe(callback){
	    add callback to list 
		return unsubscribe fn
	 
	 
	 }

     notify(){
	  loop over list 
	  call every function
	 
	 }
	 
	 setValue(key, value){
	 change state 
	 notify subscribers with new state

     }





```


list is an array of callback functions,  called by notify() on state change

Implementation 

```js
class Subject{
  #subscribers = []   // # means private,
  #state = {} 

 
	  subscribe(fn){
           // adding the callback to the subscribers array
		  this.#subcribers.push(fn)



             // unsubscribe function, when called will filter the array for fn, and return 
			 // array without fn, this is possible because its a closure function
			 return () => {

			  this.#subscribers = this.#subscribers.filter(sfn => sfn != fn)

			 }



	 }
	 
	    setValue(key, value){
             
			 // metaprogramming for setting a property to an object 
			 // same as Object[key] = val, 
			 let result = Reflect.set(this.#state, key, value)


             // reflect returns true if set was a success
			 if(result)

			   this.#notify()  // notify all the subs of the change

			 }

        }
	 
	 
	   
     // looping over all subs and notifying them with the new state
	 #notify(){

	    this.#subscribers.forEach(sfn => sfn(this.#state))

	 }
	 
	 


}





```

  
Usage
  
 ```js
 
 let subject = new Subject()

  
  

let sub1 = subject.subscribe((state)=> {

  console.log("sub1",state)

})

  
  

let sub2 = subject.subscribe((state)=> {

  console.log("sub2",state)

})

  
  

let sub3 = subject.subscribe((state)=> {

 console.log("sub3",state)

})

  

let time1 = setTimeout(() => {

	 sub3()  // unsubscribing 

	 sub2()

	 clearTimeout(time1)

}, 4000);


// changing state 

let index = 0;

let int = setInterval(() => {

	 subject.setValue("index", index)



	 index++;

}, 3000);
 
 
 
 ```
  
  
While powerful, Observer pattern is limited in what it can do, for example what if we need multiple objects to communicate with each other rather than a single object, we definitely cannot make them all subjects, that would be a nightmare to maintain and keep track off, that is where PubSub comes in
  

## PubSub
 PubSub object maintains a list of channels and subscribers to those channels, instead of observing an object, channels are observed and any change to a channel notifies the subscribers, the interesting part is PubSub does not manage the change an object outside PubSub notifies PubSub with the change on a specific channel and all objects listening on that channel will be notified
 
 ```python 
 
 // pseudo
 
 class PubSub{
    subscribers = {channel : [list of subscribers]}
	
	subscribe(channel, callback){
	   if channel does not exist:
	     create a new channel and push the callback
	   else push the callback to channel
	   
	   
	   return unsubscribe function
 
       }
	   
	   // destructuring data(arguments) into an array to handle arguments of any size 
	   // this way pubsub is object agnostic, can work with an number of arguments
	 notify(channel, ...data){
	    if(channel exist)
		  notify every subscriber giving it the data
	    
	 }
 }
 
 
 
 ```

Implementation

```js
class PubSub{

  

	 #subscribers = {}





	 subscribe(channel,fn){

		 if(!this.#subscribers[channel]) {

		    this.#subscribers[channel] = []

		 }

		   this.#subscribers[channel].push(fn)




		 return () => {

		    this.#subscribers[channel] = this.#subscribers[channel].filter(sfn => sfn != fn)

		 }




	 }



		 notify(channel, ...data){

			 if(this.#subscribers[channel]){

				 this.#subscribers[channel].forEach(fn => {

				 fn(...data)

			 })

		  }

	    }

}





```

Usage 

```js

 const pub = new PubSub()
 
 let unsub1 = pub.subscribe("Hodo", (...data)=> {  // subbing to channel hodo
                                                   // spreading arguments into an array, to handle any number of args

     console.log(data)

 })
 
 let unsub2 = pub.subscribe("Danny", (...data)=> {

     console.log(data)

  })
  
  
    setInterval(() => {

	 pub.notify("Hodo", "hodo", "hodo", "hodo")  // notifying channel Hodo with 3 arguments(...data)

	 pub.notify("Danny", "Mother of Dragons") // single argument

   }, 2000);



```

PubSub is very versatile and powerful as a start to object communication. now you should be able to knit any number of objects together and establish reactive communication 

## Thank you 

Thank you for reading, if you found this useful or not feedback is greatly appreciated



If you want to level up your JavaScript, want to close that gap between beginner and advanced beginner quickly or you are a framework person and never had a chance to dive in JS, I am publishing an eBook soon  [JavaScript for advanced beginners](https://sk76.gumroad.com/l/JS4AdvancedB?_ga=2.231950431.1783815175.1630970910-637662627.1625442646) which covers a range of topics from code completion, OOJS, iterators and generators, computational media, metaprogramming and more, and  available for pre-order

or 

You need a personal JS mentor, whether you are a beginner looking for a path, or you just want to level up your JS, or maybe you are stuck and seeing no direction or growth shoot me an email: mhlungusk@gmail.com or better yet a DM: [![Twitter URL](https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Ftwitter.com%2FMhlunguSfundo)](https://twitter.com/MhlunguSfundo)