the observer pattern · the observer pattern † intent: define a one-to-many dependency between...
TRANSCRIPT
Supplement toThe Design and Implementation of Multimedia Software
The Observer Pattern
Prof. David Bernstein
James Madison University
users.cs.jmu.edu/bernstdh
D. Bernstein (JMU) Observer www.cs.jmu.edu 1 / 21
Motivation
• Objects often need to communicate with each other
• Traditional message passing techniques tend to couple objects tootightly
D. Bernstein (JMU) Observer www.cs.jmu.edu 2 / 21
An Example
A security (e.g., stocks, futures, options) trading application in whichthere is a TickReader that reads “tick by tick” pricing information(e.g., from the Internet) and sends each Tick to a TickWriter thatsaves the information in a file and to a TickerTape that displays theinformation on a screen.
D. Bernstein (JMU) Observer www.cs.jmu.edu 3 / 21
An Example - A Bad Design
Think of the TickReader as actively adding ticks to the TickWriterand TickerTape.
D. Bernstein (JMU) Observer www.cs.jmu.edu 4 / 21
Problems with this Design
• Because TickReader calls the TickWriter and TickerTape it isnot very re-usable
• Every TickReader must have an associated TickWriter andTickerTape
D. Bernstein (JMU) Observer www.cs.jmu.edu 5 / 21
An Example - A Better Design
Think of the TickWriter and TickerTape as passively listening for“ticks”. Then, a TickReader need only have a list of (zero or more)TickListener objects that it will inform.
D. Bernstein (JMU) Observer www.cs.jmu.edu 6 / 21
The Observer Pattern
• Intent:Define a one-to-many dependency between objects so that when oneobject changes state, all of its dependents are notified
• Participants:A subject
Some observers
D. Bernstein (JMU) Observer www.cs.jmu.edu 7 / 21
One Implementation
D. Bernstein (JMU) Observer www.cs.jmu.edu 8 / 21
Another Implementation
D. Bernstein (JMU) Observer www.cs.jmu.edu 9 / 21
Issues Related to the Choice of Collection
• Frequency of notifications vs. modifications (compare Hashtableor HashMap with Vector or ArrayList)
• Need for concurrent notifications and modifications (think aboutCopyOnWriteArrayList)
D. Bernstein (JMU) Observer www.cs.jmu.edu 10 / 21
Other Terminology
• Listener
• Publish-Subscribe
D. Bernstein (JMU) Observer www.cs.jmu.edu 11 / 21
A Complete Example
• A Silly Text Processor:Counts the number of words that start with an uppercase letter
Save the lines to a file
Shows the progress (e.g., then number of lines processed)
• Some Observations:This is not going to make us any money
We can use it to explore different designs
D. Bernstein (JMU) Observer www.cs.jmu.edu 12 / 21
A Design that is Not Cohesive
D. Bernstein (JMU) Observer www.cs.jmu.edu 13 / 21
A Design that is Tightly Coupled
D. Bernstein (JMU) Observer www.cs.jmu.edu 14 / 21
A Good Design
D. Bernstein (JMU) Observer www.cs.jmu.edu 15 / 21
The LineObserver Interface
public interface LineObserver
{
public void handleLine(LineSubject source);
}
D. Bernstein (JMU) Observer www.cs.jmu.edu 16 / 21
The LineSubject Interface
public interface LineSubject
{
public void addObserver(LineObserver observer);
public String getLine();
public void notifyObservers();
public void removeObserver(LineObserver observer);
}
D. Bernstein (JMU) Observer www.cs.jmu.edu 17 / 21
The LineReader
import java.io.*;
import java.util.*;
public class LineReader implements LineSubject
{
private BufferedReader in;
private List<LineObserver> observers;
private int maxLines;
private String line;
public LineReader(InputStream is, int maxLines) throws IOException
{
this.maxLines = maxLines;
in = new BufferedReader(new InputStreamReader(is));
observers = new LinkedList<LineObserver>();
}
public void addObserver(LineObserver observer)
{
observers.add(observer);
}
D. Bernstein (JMU) Observer www.cs.jmu.edu 18 / 21
The LineReader (cont.)
public String getLine()
{
return line;
}
public void notifyObservers()
{
Iterator<LineObserver> i;
LineObserver observer;
i = observers.iterator();
while (i.hasNext())
{
observer = i.next();
observer.handleLine(this);
}
}
public void removeObserver(LineObserver observer)
{
observers.remove(observer);
}
D. Bernstein (JMU) Observer www.cs.jmu.edu 19 / 21
The LineReader (cont.)
public void start() throws IOException
{
// Read from the console and alert listeners
while ((line = in.readLine()) != null)
{
notifyObservers();
}
}
}
D. Bernstein (JMU) Observer www.cs.jmu.edu 20 / 21
The SillyTextProcessor
// Initialization
reader = new LineReader(System.in, maxLines);
bar = new ProgressWindow(maxLines);
archiver = new LineArchiver();
counter = new UCWordCounter();
reader.addObserver(bar);
reader.addObserver(archiver);
reader.addObserver(counter);
// Prompt the user
System.out.println("Enter " +maxLines +
" lines of text (^Z to end):\n");
reader.start();
D. Bernstein (JMU) Observer www.cs.jmu.edu 21 / 21