Define a one-to-many dependency between objects so that when one object changes state,The Observer pattern helps create a family of cooperating classes, while maintaining consistency and avoiding tight-coupling.
all its dependents are notified and updated automatically.
When To Use
- In a mailing list, where every time an event happens (a new product, a gathering, etc.) a message is sent to the people subscribed to the list.
- When a change to one object requires changing others, and you don't know how many objects need to be changed.
- When an object should be able to notify other objects without making assumptions about who these objects are (avoid tight-coupling).
Pros and Cons
- Loose coupling between Subject and Observer: The subject knows only a list of observers, that implement the Observer interface, it does no know the concrete implementation of the Observer.
- Broadcast communication: An event notification is broadcast observers irrespective of the number of Observers
- Unexpected updates: The can be blind to the cost of changing the subject.
Issues
- Mapping subjects to their observers: A subject can keep track it's observers as a list of all observer references or in a hash table, depending on whether space of time is the criteria respectively.
- Observing more than one subject: Using the Observer pattern you can implement a many-to-many relationship between subjects and observers. In this case, the Observer may need to know which subject is sending the notification. One way is to pass the Subject as an argument to the Update operation.
- Who triggers the update (Notify operation in Subject):
- State setting operation in subject to trigger Notify.
- Client trigger Notify at the right time.
- Dangling references to deleted subjects: Deleting a subject or a observer should not produce dangling references.
- Making sure subject state is self-consistent before notification: Otherwise, an observer can query subject's intermediate state through GetState operation.
- Avoiding observer-specific update protocols: push and pull models:
- Push model: subject sends details change information to observer, for this the subject has to know about the Observers.
- Pull model: subject sends minimum change information to observer and observer query for the rest of the information, as a result there might be more method calls that necessary.
- Specifying modifications of interest explicitly: One can register observer for only specific events. This can improve update efficiency.
- Subject: Maintains a list of Observer references. Subject also provides an interface for attaching and detaching Observer objects.
- Observer: Defines an updating interface for objects that should be notified of changes in a subject.
- ConcreteSubject: Stores state of interest to ConcreteObserver objects and sends notifications to its observers upon state changes.
- ConcreteObserver: Maintains a reference to a ConcreteSubject object and a state that should stay consistent with the subject's.
package patterns;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
interface Subject {
public void addObserver(Observer o);
public void removeObserver(Observer o);
public String getState();
public void setState(String state);
}
interface Observer {
public void update(Subject o);
}
class ObserverImpl implements Observer {
private String state = "";
public void update(Subject o) {
state = o.getState();
System.out.println("Update received from Subject, state changed to : " + state);
}
}
class SubjectImpl implements Subject {
private List observers = new ArrayList();
private String state = "";
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
notifyObservers();
}
public void addObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
public void notifyObservers() {
Iterator i = observers.iterator();
while (i.hasNext()) {
Observer o = (Observer) i.next();
o.update(this);
}
}
}
public class ObserverTest {
public static void main(String[] args) {
Observer o = new ObserverImpl();
Subject s = new SubjectImpl();
s.addObserver(o);
s.setState("New State");
}
}
No comments:
Post a Comment