Table of Contents
As described by GoF:
“Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically”.
You can think of observer design pattern in two ways
- Subject-Observer relationship:Object which is being observed is refereed as Subject and classes which observe subject are called Observer
- Publisher-Subscriber relationship:A publisher is one who publish data and notifies it to the list of subscribers who have subscribed for the same to that publisher. A simple example is Newspaper. Whenever a new edition is published by the publisher,it will be circulated among subscribers whom have subscribed to publisher.
The observers will not monitor every time whether there is any change in state of subject or not, since they will be notified for every state change of subject, until they stop observing subject. So it follows hollywood principle-“Don’t call us,we will call you”.
Some real life examples:
On facebook also,If you subscribe someone then whenever new updates happen then you will be notified.
When to use it:
- When one object changes its state,then all other dependents object must automatically change their state to maintain consistency
- When subject doesn’t know about number of observers it has.
- When an object should be able to notify other objects without knowing who objects are.
 UML diagram for observer design pattern:
Components:
Subject
- Knows its observers
- Has any number of observer
- Provides an interface to attach and detaching observer object at run time
Observer
- Provides an update interface to receive signal from subject
ConcreteSubject
- Stores state of interest to ConcreteObserver objects.
- Send notification to it’s observer
ConcreteObserver
- Maintains reference to a ConcreteSubject object
- Maintains observer state consistent with subjects.
- Implements update operation
Java in-built API for observer pattern:
java.util.Observable:
java.util.Observer:
public void update(Observable obj, Object arg) :This method is called whenever the observed object is changed. An application calls an Observable object’s notifyObservers method for notifying to all the observers of change.
Example:
Java code:
1.Subject.java:
1 2 3 4 5 6 7 8 9 |
package org.arpit.javapostsforlearning; public interface Subject { Â Â Â Â public void registerObserver(Observer observer); Â Â Â Â public void removeObserver(Observer observer); Â Â Â Â public void notifyObservers(); } |
2.Product.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
package org.arpit.javapostsforlearning; import java.util.ArrayList; public class Product implements Subject{ private ArrayList observers = new ArrayList(); private String productName; private String productType; String availability; public Product(String productName, String productType,String availability) { super(); this.productName = productName; this.productType = productType; this.availability=availability; } public ArrayList getObservers() { return observers; } public void setObservers(ArrayList observers) { this.observers = observers; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductType() { return productType; } public void setProductType(String productType) { this.productType = productType; } public String getAvailability() { return availability; } public void setAvailability(String availability) { this.availability = availability; notifyObservers(); } public void notifyObservers() { System.out.println("Notifying to all the subscribers when product became available"); for (Observer ob : observers) { ob.update(this.availability ); } } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } } |
3.Observer.java:
1 2 3 4 5 6 |
package org.arpit.javapostsforlearning; public interface Observer { public void update(String availability); } |
4.Person.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package org.arpit.javapostsforlearning; public class Person implements Observer{ String personName; public Person(String personName) { this.personName = personName; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public void update(String availabiliy) { System.out.println("Hello "+personName+", Product is now "+availabiliy+" on flipkart"); } } |
5.ObserverPatternMain.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package org.arpit.javapostsforlearning; public class ObserverPatternMain {    /**    * @Author arpit mandliya    */    public static void main(String[] args) {       Person arpitPerson=new Person("Arpit");       Person johnPerson=new Person("John");             Product samsungMobile=new Product("Samsung", "Mobile", "Not available");             //When you opt for option "Notify me when product is available".Below registerObserver method       //get executed       samsungMobile.registerObserver(arpitPerson);       samsungMobile.registerObserver(johnPerson);             //Now product is available       samsungMobile.setAvailability("Available");          } } |
Run it:
1 2 3 4 5 |
Notifying to all the subscribers when product became available Hello Arpit, Product is now Available on flipkart Hello John, Product is now Available on flipkart |
Using java inbuilt APIs:
1.Product.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
package org.arpit.javapostsforlearning; import java.util.ArrayList; import java.util.Observable; import java.util.Observer; public class Product extends Observable{ Â private ArrayList observers = new ArrayList(); private String productName; private String productType; String availability; public Product(String productName, String productType,String availability) { super(); this.productName = productName; this.productType = productType; this.availability=availability; } public ArrayList getObservers() { return observers; } public void setObservers(ArrayList observers) { this.observers = observers; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getProductType() { return productType; } public void setProductType(String productType) { this.productType = productType; } public String getAvailability() { return availability; } public void setAvailability(String availability) { if(!(this.availability.equalsIgnoreCase(availability))) { this.availability = availability; setChanged(); notifyObservers(this,availability); } } public void notifyObservers(Observable observable,String availability) { System.out.println("Notifying to all the subscribers when product became available"); for (Observer ob : observers) { ob.update(observable,this.availability); } } public void registerObserver(Observer observer) { observers.add(observer); } public void removeObserver(Observer observer) { observers.remove(observer); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
package org.arpit.javapostsforlearning; import java.util.Observable; import java.util.Observer; public class Person implements Observer{ String personName; public Person(String personName) { this.personName = personName; } public String getPersonName() { return personName; } public void setPersonName(String personName) { this.personName = personName; } public void update(Observable arg0, Object arg1) { System.out.println("Hello "+personName+", Product is now "+arg1+" on flipkart"); } } |
3.ObserverPatternMain.java:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
package org.arpit.javapostsforlearning; public class ObserverPatternMain {    /**    * @Author arpit mandliya    */    public static void main(String[] args) {       Person arpitPerson=new Person("Arpit");       Person johnPerson=new Person("John");             Product samsungMobile=new Product("Samsung", "Mobile", "Not available");             //When you opt for option "Notify me when product is available".Below registerObserver method       //get executed      samsungMobile.registerObserver(arpitPerson);       samsungMobile.registerObserver(johnPerson);             //Now product is available       samsungMobile.setAvailability("Available");           } } |
Run it:
1 2 3 4 5 |
Notifying to all the subscribers when product became available Hello Arpit, Product is now Available on flipkart Hello John, Product is now Available on flipkart |
Some important points about observer pattern:
- Loose coupling between Subject and Observer:Only thing subject know about its observers is that observer implements Observer interface.You can register or delete any observer without affecting subject.
- Support for broadcast communication:Notification about subject state change does not need to specify its receiver.This notification is broadcasted to all interested object that subscribed to it.
- The one of the problem with this pattern is that debugging become very hard,if you have large number of subscribers because flow of control is implicit between subject and observers.
- Spurious updates:If criteria for state change is not well defined then sometimes it lead to spurious updates.
Source code:
1 2 3 4 |
<b>Source:</b><a href="https://dl.dropbox.com/s/da3vj0uwn9nji0d/ObserverDesignPatternExample.rar" target="_blank">Download without java API</a> <b>Source + lib</b>: <a href="https://dl.dropbox.com/s/y09zpgkp4ow8w60/ObserverDesignPatternJavaAPIExample.rar" target="_blank">Download with java API</a> |