the observer pattern · the observer pattern † intent: define a one-to-many dependency between...

21
Supplement to The 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

Upload: others

Post on 15-Jul-2020

11 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 2: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 3: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 4: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 5: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 6: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 7: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 8: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

One Implementation

D. Bernstein (JMU) Observer www.cs.jmu.edu 8 / 21

Page 9: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

Another Implementation

D. Bernstein (JMU) Observer www.cs.jmu.edu 9 / 21

Page 10: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 11: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

Other Terminology

• Listener

• Publish-Subscribe

D. Bernstein (JMU) Observer www.cs.jmu.edu 11 / 21

Page 12: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 13: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

A Design that is Not Cohesive

D. Bernstein (JMU) Observer www.cs.jmu.edu 13 / 21

Page 14: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

A Design that is Tightly Coupled

D. Bernstein (JMU) Observer www.cs.jmu.edu 14 / 21

Page 15: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

A Good Design

D. Bernstein (JMU) Observer www.cs.jmu.edu 15 / 21

Page 16: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

The LineObserver Interface

public interface LineObserver

{

public void handleLine(LineSubject source);

}

D. Bernstein (JMU) Observer www.cs.jmu.edu 16 / 21

Page 17: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 18: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 19: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 20: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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

Page 21: The Observer Pattern · The Observer Pattern † Intent: Define a one-to-many dependency between objects so that when one object changes state, all of its dependents are notified

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