For 2 minutes write down whatever comes to mind about the last class
This could be topics you learned
Questions you had
Connections you made
A Weather Monitoring Application
We have a weather station with humidity, temperature, and pressure sensors
We are implementing a Weather Data object that pulls data from the weather station.
Create an app that uses the Weather Data object to update three different displays:
current conditions
weather stats
forecast
Problem Specification
The WeatherData class has getters and setters for temperature, humidity, and pressure
The measurementsChanged() method is called anytime new weather data is available
We don’t know or care how!
We need to implement three different display elements that use the weather data
The system must be expandable, in case others want to add other display elements later
A First Attempt At Coding
public class WeatherData {
//instance variable declarations
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// other methods
}
What’s wrong?
A First Attempt At Coding
public class WeatherData {
//instance variable declarations
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// other methods
}
What’s wrong?
Coding to implementations: adding displays requires changing the program
A First Attempt At Coding
public class WeatherData {
//instance variable declarations
public void measurementsChanged() {
float temp = getTemperature();
float humidity = getHumidity();
float pressure = getPressure();
currentConditionsDisplay.update(temp, humidity, pressure);
statisticsDisplay.update(temp, humidity, pressure);
forecastDisplay.update(temp, humidity, pressure);
}
// other methods
}
What’s wrong?
Coding to implementations: adding displays requires changing the program
Encapsulate things that change!
Publish/Subscribe
Newspapers and magazines
Email lists
RSS feeds
Following someone on Twitter
You subscribe and receive any new additions
You unsubscribe and stop receiving anything
The Observer Pattern
The Observer Pattern defines a one-to-many dependency between objects so that when one object changes state, all its dependencies are notified and updated automatically.
The Observer Pattern Vocabulary
If you understand how newspaper subscriptions work then you basically already understand the observer pattern.
However, instead saying publisher as we would in the newspaper example we instead say Subject and instead of saying subscribers we say Observers
The Observer Pattern
The Observer Pattern
Objects use the Subject interface to (de)register as observers
Each subject can have many observers
All potential observers need to implement the Observer interface and provide the update() method
A concrete subject always implements the Subject interface and the notifyObservers() method
Concrete observers can be any class that implements the Observer interface and registers with a concrete subject
The Power of Loose Coupling
The only thing a subject knows about an observer is that it implements a given interface
We can add new observers at any time
We never need to modify the subject to add new types of observers
We can reuse subjects or observers independently of each other
Changes to either the subject or an observer will not affect each other
Loosely coupled designs allow us to build flexible OO systems that can handle change because they minimize the interdependencies between objects.
Weather Data Interfaces
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();
}
Any potential problems with this?
Implementing The Subject Interface
public class WeatherData implements Subject {
private List<Observer> observers;
private float temperature;
private float humidity;
private float pressure;
public WeatherData() {
observers = new ArrayList<>();
}
public void registerObserver(Observer o) {
observers.add(o);
}
public void removeObserver(Observer o) {
observers.remove(o);
}
}
Notify Methods
public void notifyObservers() {
for(Observer observer : observers) {
observer.update(temperature, humidity, pressure);
}
}
public void measurementsChanged() {
notifyObservers();
}
A Display Element
public class CurrentConditionsDisplay
implements Observer, DisplayElement {
private float temperature;
private float humidity;
private Subject weatherData;
public CurrentConditionsDisplay(Subject weatherData) {
this.weatherData = weatherData;
weatherData.registerObserver(this);
}
public void update(float temp, float humidity, float pressure) {
this.temperature = temp;
this.humidity = humidity;
display();
}
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
Java’s Built-In Observer Pattern
Java provides the Observer interface and the Observable class in the package java.util
Similar to Subject and Observer
Must extend Observable rather than implement Subject
Another Design…
The Java Observer Pattern
For an object to become an observer
Just implement the Observer interface (as before)
For the observable to send notifications
Become observable by extending the java.util.Observable superclass
Call the setChanged() method to signify that the state of the object has changed
Call one of two notification methods:
notifyObservers()
notifyObservers(Object arg)
The Dark Side of Java Observables
Observable is a class, not an interface
You have to subclass it, so you can’t add the Observable behavior onto a class that already extends something else
Limits reuse potential
Because there’s no Observable interface, you cannot create your own implementations of Observables
Observable protects crucial methods
E.g., setChanged() can only be called by subclasses
Limits flexibility
You cannot favor composition over inheritance
Should I Use Java Observables?
Short Answer: NO
Java’s Observable library was deprecated in Java 9
This does not mean that the observer pattern is deprecated just that this particular implementation is
What should you use instead?
You can roll your own implementation to have more flexibility and control
Use PropertyChangeSupport/Listener from java.beans but with many caveats
What Is A Bean?
Standard describing a class that has the following properties:
All fields are private and have getters/setters
Has a public no argument constructor
Implements Serializable
What Is Serializable?
An interface which allows your object to be serialized/deserialized
By serializing an object you transform it into a stream of bytes
It can then be saved to disk or sent over the network
Deserializing is the reverse, turning a stream of bytes into an object
Can you see the problem?
Risks Of Serializing
Bytes can easily be manipulated and made to harm your computer!
It also means that nothing in your object (which is included in serialization) can ever change!
Item 85 and 86 in Effective Java go into this topic more in depth
Long story short avoid Serializable in most cases
What About Observable Then?
So then what is the best way to implement this pattern?