observer design pattern 10-16-2013 - clarkson...
TRANSCRIPT
Observer Design Pattern
10-16-2013
ICPC
Northeast North America Preliminary sponsored by the
Clarkson Student Chapter of the ACM
Saturday, October 19, 2013
11:00 am – 5:00 pm
Applied CS Labs Science Center 334-336
More on the Observer Design Pattern implement Subject & Observer interfaces use java.util.Observer & java.util.Observable
Model-View-Controller (MVC)
Exam#1: Wed, October 16th, 7:00 pm, SC162
Project#1: due Wed, October 30th
Subject is an interface
Subject is a class
public interface Subject { public void registerObserver(Observer o); public void removeObserver(Observer o); public void notifyObservers(); }
public interface Observer { public void update(float temp, float humidity, float pressure); }
public interface DisplayElement { public void display(); }
public class WeatherData implements Subject { private List observers; // maintains a list of observers /** adds an observer to the list */ public void registerObservers(Observer o) { } /** removes an observer from the list */ public void removeObservers(Observer o) { } /** notifies all observers on the list */ public void notifyObservers() { for (Observer o : observers) o.update(temperature, humidity, pressure); }
public void measurementsChanged() { notifyObservers();}
public void setMeasurements(float t, float h, float p) { update measurements & calls measurementsChanged(); } }
public class CurrentConditionsDisplay implements Observer { public void update(float t, float h, float p) { this.temperature = t; this.humidity = h; display(); } public void display() { /* display code goes here */ } }
public class WeatherStatsDisplay implements Observer // similar to the above
public class ForecastDisplay implements Observer // similar to the above
1 subject (Watch2Windows)
2 observers (Color View and List View)
Write your own interfaces for Observer & Subject
public interface Observer {
/** notify Observers that a change has occurred */
public void sendNotify(String s);
}
public interface Subject
{
/** register your interest in the subject */
public void registerInterest(Observer obs);
}
public class Watch2Windows extends WindowFrame
implements ActionListener, ItemListener, Subject {
private List observers;
private ColorFrame cframe;
private ListFrame lframe;
//------------------------------------------
public Watch2Windows() {
observers = new ArrayList(); //observing frames
//---------create observers---------
cframe = new ColorFrame(this);
lframe = new ListFrame(this);
}
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED)
notifyObservers((JRadioButton)e.getSource());
}
private void notifyObservers(JRadioButton rad) {
String color = rad.getText();
for (int i=0; i< observers.size(); i++) {
((Observer)(observers.get(i))).sendNotify(color);
}
}
public void registerInterest(Observer obs) {
observers.add(obs); //adds observer to list
}
public class ColorFrame extends JFrame
implements Observer {
public ColorFrame( Subject s ) {
super(“Color View”);
s.registerInterest(this);
}
public void sendNotify(String s) {
color_name = s;
if (s.equalsIgnoreCase("RED")) color = Color.red;
if (s.equalsIgnoreCase("BLUE")) color = Color.blue;
if (s.equalsIgnoreCase("GREEN")) color = Color.green;
setBackground(color);
}
}
public class ListFrame extends JFrame
implements Observer {
private JList list;
private JListData listData;
public ListFrame( Subject s) {
super(“List View”);
s.registerInterest(this);
listData = new JListData(); // the list model
list = new JList(listData); // the visual list
}
public void sendNotify(String s) {
listData.addElement(s);
}
}
Use the java.util.Observer interface and the java.util.Observable class
/** any class can implement this interface to be an observer */
public interface Observer {
/** application calls notifyObservers() which automatically calls this method for each registered observer */
public void update(Observable o, Object arg);
}
2 subjects:
Account 1
Account 2
3 observers
Account1 view
Account2 view
Pie chart of
assets
/** represents an “observable” object, aka subject or model */
public class Observable extends Object {
// void addObserver(Observer o)
// void deleteObserver(Observer o)
// int countObservers()
// boolean hasChanged()
// protected void setChanged()
// protected void clearChanged()
/** if data has changed (as indicated by setChanged), then notify all observers and then clearChanged */
void notifyObservers();
}
// Account is an Observable class that represents a bank
// account in which funds may be deposited or withdrawn.
package com.deitel.account;
import java.util.Observable;
public class Account extends Observable // subject
{ // set Account balance and notify observers of change
private void setBalance( double accountBalance ) {
balance = accountBalance; // must call setChanged before notifyObservers
// to indicate model has changed
setChanged(); // notify Observers that model has changed
notifyObservers();
}
public abstract class AbstractAccountView
extends JPanel
implements Observer { // observer
public AbstractAccountView(Account observableAccount )
throws NullPointerException {
// register as an Observer to receive account updates
observableAccount.addObserver( this );
}
// receive updates from Observable Account
public void update( Observable observable, Object object ) {
updateDisplay();
}
}
// AssetPieChartView is an AbstractAccountView subclass that
// displays multiple asset Account balances as a pie chart.
public class AssetPieChartView extends JPanel
implements Observer { // observes all accounts private List accounts = new ArrayList(); // List of observed accts // add Account to pie chart view
public void addAccount( Account anAccount ) {
if ( anAccount == null ) // do not add null Accounts
throw new NullPointerException(); // add new account to the list of accounts
accounts.add( account ); // register as Observer to receive Account updates
anAccount.addObserver( this ); // update display with new Account information
repaint();
}
// remove Account from pie chart view
public void removeAccount( Account anAccount ) {
anAccount.deleteObserver( this ); // stop receiving updates
accounts.remove(anAccount );// remove Account from accounts list
colors.remove(anAccount ); // remove Account's Color
repaint(); // update display to remove Account information
}
// receive updates from Observable Account
public void update( Observable observable, Object object ) {
repaint();
}
// AccountController is a controller for Accounts. It provides
// a JTextField for inputting a deposit or withdrawal amount
// and JButtons for depositing or withdrawing funds.
public class AccountController extends JPanel {
private Account account; // Account to control
} // AccountManager is an application that uses the MVC design
// pattern to manage bank Account information.
public class AccountManager extends JFrame {
public AccountManager() {
super( "Account Manager" );
// create account1 with initial balance
Account account1 = new Account( "Account 1", 1000.00 );
/* continuation of constructor for AccountManager */
// create GUIs for account1
JPanel account1Panel = createAccountPanel( account1 );
// create account2 with initial balance
Account account2 = new Account( "Account 2", 3000.00 );
// create GUI for account2
JPanel account2Panel = createAccountPanel( account2 );
// create AccountPieChartView to show Account pie chart
AssetPieChartView pieChartView =
new AssetPieChartView();
// add both Accounts to AccountPieChartView
pieChartView.addAccount( account1 );
pieChartView.addAccount( account2 );
} // end AccountManager constructor
import java.util.Observer;
For an object to become an observer… implement the Observer interface
call addObserver() to add to the list
call deleteObserver() to remove from the list
write a method update(Observable o, Object arg)
import java.util.Observable;
For an object to become a “subject”
write a subclass of Observable
call the setChanged() method when the state changes in your object
call notifyObservers() or notifyObservers(Object arg )
Observable is a class, not an interface
in Observable setChanged() is protected, so have to subclass
so, can’t favor composition over inheritance
Model
uses the Observer Design Pattern
the model is the Subject
the controller and views are Observers
keeps the views and controllers updated on state changes
View
uses the Strategy Design Pattern,
and uses the Composite Design Pattern
(the view is a composite of GUI components)
Controller
uses the Strategy Design Pattern
The Composite Design Pattern allows you to compose objects into tree structures to represent hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly
Applies to Scene Graphs (the tree is a composite)