Observ­er is a behav­ioral design pat­tern that lets you define a sub­scrip­tion mech­a­nism to noti­fy mul­ti­ple objects about any events that hap­pen to the object they’re observing.

Problem: An object that changes its state often. Multiple views of the current state

Solution: model a 1-to-many dependency between objects. Connect the state of an observed object, the subject with many observing objects, and the observers

The object that has some inter­est­ing state is often called sub­ject, but since it’s also going to noti­fy other objects about the changes to its state, we’ll call it pub­lish­er. All other objects that want to track changes to the pub­lish­er’s state are called sub­scribers.

Mech­a­nism

  1. an array field for stor­ing a list of ref­er­ences to sub­scriber objects
  2. sev­er­al pub­lic meth­ods which allow adding sub­scribers to and remov­ing them from that list.

It’s cru­cial that all sub­scribers imple­ment the same inter­face and that the pub­lish­er com­mu­ni­cates with them only via that inter­face. This inter­face should declare the noti­fi­ca­tion method along with a set of para­me­ters that the pub­lish­er can use to pass some con­tex­tu­al data along with the notification.

image.png

Pub­lish­er noti­fies sub­scribers by call­ing the spe­cif­ic noti­fi­ca­tion method on their objects.

Pub­lish­er noti­fies sub­scribers by call­ing the spe­cif­ic noti­fi­ca­tion method on their objects.

If your app has sev­er­al dif­fer­ent types of pub­lish­ers and you want to make your sub­scribers com­pat­i­ble with all of them, you can go even fur­ther and make all pub­lish­ers fol­low the same inter­face.

This inter­face would only need to describe a few sub­scrip­tion meth­ods. The inter­face would allow sub­scribers to observe pub­lish­ers’ states with­out cou­pling to their con­crete classes.

Structure

image.png

The observer pattern decouples a subject from its observer

The observer pattern decouples a subject from its observer

3 variants for maintaining the consistency

Notification + pull:

every time the state of the Subject changes, notify() is called which calls update() in each Observer

An observer can decide whether to pull the state of the Subject by calling getState()

Notification + push:

the Subject also includes the state that has been changed in each update(state) call

Periodic pull:

an Observer periodically (e.g. every 5s) pulls the state of the Subject by calling getState()

  1. The Pub­lish­er issues events of inter­est to other objects. These events occur when the pub­lish­er changes its state or exe­cutes some behav­iors. Pub­lish­ers con­tain a sub­scrip­tion infra­struc­ture that lets new sub­scribers join and cur­rent sub­scribers leave the list.
  2. When a new event hap­pens, the pub­lish­er goes over the sub­scrip­tion list and calls the noti­fi­ca­tion method declared in the sub­scriber inter­face on each sub­scriber object.
  3. The Sub­scriber inter­face declares the noti­fi­ca­tion inter­face. In most cases, it con­sists of a sin­gle update method. The method may have sev­er­al para­me­ters that let the pub­lish­er pass some event details along with the update.
  4. Con­crete Sub­scribers per­form some actions in response to noti­fi­ca­tions issued by the pub­lish­er. All of these class­es must imple­ment the same inter­face so the pub­lish­er isn’t cou­pled to con­crete classes.
  5. Usu­al­ly, sub­scribers need some con­tex­tu­al infor­ma­tion to han­dle the update cor­rect­ly. For this rea­son, pub­lish­ers often pass some con­text data as argu­ments of the noti­fi­ca­tion method. The pub­lish­er can pass itself as an argu­ment, let­ting sub­scriber fetch any required data directly.
  6. The Client cre­ates pub­lish­er and sub­scriber objects sep­a­rate­ly and then reg­is­ters sub­scribers for pub­lish­er updates.”

<aside>

Applicability

image.png

<aside>

How to Implement

  1. Look over your busi­ness logic and try to break it down into two parts: the core func­tion­al­i­ty, inde­pen­dent from other code, will act as the pub­lish­er; the rest will turn into a set of sub­scriber classes.
  2. Declare the sub­scriber inter­face. At a bare min­i­mum, it should declare a sin­gle update method.
  3. Declare the pub­lish­er inter­face and describe a pair of meth­ods for adding a sub­scriber object to and remov­ing it from the list. Remem­ber that pub­lish­ers must work with sub­scribers only via the sub­scriber interface
  4. Decide where to put the actu­al sub­scrip­tion list and the imple­men­ta­tion of sub­scrip­tion meth­ods. Usu­al­ly, this code looks the same for all types of pub­lish­ers, so the obvi­ous place to put it is in an abstract class derived direct­ly from the pub­lish­er inter­face. Con­crete pub­lish­ers extend that class, inher­it­ing the sub­scrip­tion behavior.

How­ev­er, if you’re apply­ing the pat­tern to an exist­ing class hier­ar­chy, con­sid­er an approach based on com­po­si­tion: put the sub­scrip­tion logic into a sep­a­rate object, and make all real pub­lish­ers use it.

  1. Cre­ate con­crete pub­lish­er class­es. Each time some­thing impor­tant hap­pens inside a pub­lish­er, it must noti­fy all its subscribers.
  2. Imple­ment the update noti­fi­ca­tion meth­ods in con­crete sub­scriber class­es. Most sub­scribers would need some con­text data about the event. It can be passed as an argu­ment of the noti­fi­ca­tion method.

But there’s anoth­er option. Upon receiv­ing a noti­fi­ca­tion, the sub­scriber can fetch any data direct­ly from the noti­fi­ca­tion. In this case, the pub­lish­er must pass itself via the update method. The less flex­i­ble option is to link a pub­lish­er to the sub­scriber per­ma­nent­ly via the constructor.

  1. The client must cre­ate all nec­es­sary sub­scribers and reg­is­ter them with prop­er publishers.” </aside>