Publishers-SubscriberPattern

advertisement
1)
Publishers-Subscriber / Observer Pattern (Communication)
Intent:
Define a one-to-many dependency between objects so that when one object changes
state, all its dependents are notified and updated automatically.
Structure:
Subject
+Attach(o: Observer)
+Detach(o: Observer)
+Notify()
ConcreteSubject
+subject
Observer
+Update()
ConcreteObserver
Participant Classes:
Subject: Keeps track of its observers. Provides an interface for attaching and detaching
Observer objects
Observer: Defines an interface for update notification
Concrete Subject: The object being observed. Stores state of interest to Concrete Observer
objects. Sends a notification to its observers when its state changes
Concrete Observer: The observing object. It stores state that should stay in consistent with
the subject. Implements the Observer update interface to keep its state consistent with the
participants.
Example:
Weather Information system
The weather Station will be broadcasting the current weather conditions like
temperature, humidity and biometric pressure. We have to create an application which
receives the weather conditions and displays them in different forms. (i.e. displaying the
current weather conditions, displaying weather statistics). All displays will be updating the
weather conditions in real time, as and when the new conditions are recorded.
Pattern Instance:
Subject: Weather Station
Observer: User
Concrete Subject: Weather Data
Concrete Observer: ForecastDisplay, CurrentConditionDisplay
Use Case Diagram:
System
Forecast Display
Weather Data
User
Weather Station
CurrentCondition Display
Class diagram:
ForecastDisplay
-currentPressure: float
-lastPressure: float
+ForecastDisplay(Observable)
+update(Observable, Object)
+display()
WeatherData
-temperature: float
-pressure: float
-humidity: float
+getTemperature(): float
+getPressure(): float
+getHumidity(): float
+measurementschanged(): float
+setMeasurements(theTemperature: float, thePressure: float, theHumidity: float): float
CurrentConditionDisplay
-temperature: float
-humidity: float
+CurrentConditionDisply(Observable)
+update(Observable, Object)
+display()
Sequence Diagram:
WeatherStation
+main(Strings)
: Weather Data
: CurrentCondition Display
: Forecast Display
: Weather Station
: User
1 : setMeasurements NoChange()
2 : Display Current Condition()
3 : display()
4 : ChangeInWeather()
5 : DisplayForecastData()
6 : forecast data()
Collaboration Diagram:
: Forecast Display
: Weather Data
: User
: Weather Station
Java Code:
WeatherData.java
import java.util.Observable;
public class WeatherData extends Observable {
private float temperature;
public float getTemperature() {
return temperature;
}
private float pressure;
public float getPressure() {
return pressure;
}
private float humidity;
public float getHumidity() {
return humidity;
: CurrentCondition Display
}
public void measurementschanged(){
setChanged();
notifyObservers();
}
public void setMeasurements(float theTemperature, float theHumidity, float
thePressure){
temperature=theTemperature;
pressure=thePressure;
humidity=theHumidity;
measurementschanged();
}
}
ForeCastDisplay.java:
import java.util.Observable;
import java.util.Observer;
public class ForeCastDisplay implements Observer {
private float currentPressure = 29.92f;
private float lastPressure;
public ForeCastDisplay(Observable observable) {
observable.addObserver(this);
}
public void update(Observable observable, Object arg) {
if (observable instanceof WeatherData) {
WeatherData weatherData = (WeatherData)observable;
lastPressure = currentPressure;
currentPressure = weatherData.getPressure();
display();
}
}
public void display() {
System.out.print("Forecast: ");
if (currentPressure > lastPressure) {
System.out.println("Improving weather on the way!");
} else if (currentPressure == lastPressure) {
System.out.println("More of the same");
} else if (currentPressure < lastPressure) {
System.out.println("Watch out for cooler, rainy weather");
}
}
}
CurrentConditionDisplay.java:
import java.util.Observable;
import java.util.Observer;
public class CurrentConditionDisplay implements Observer {
private float temperature;
private float humidity;
Observable observable;
public CurrentConditionDisplay(Observable observable) {
this.observable = observable;
observable.addObserver(this);
}
public void update(Observable obs, Object arg) {
if (obs instanceof WeatherData) {
WeatherData weatherData = (WeatherData)obs;
this.temperature = weatherData.getTemperature();
this.humidity = weatherData.getHumidity();
display();
}
}
public void display() {
System.out.println("Current conditions: " + temperature
+ "F degrees and " + humidity + "% humidity");
}
}
The Client:
public class WeatherStation {
public static void main(String[] args) {
WeatherData weatherData = new WeatherData();
CurrentConditionDisplay
currentConditions
=
CurrentConditionDisplay(weatherData);
ForeCastDisplay forecastDisplay = new ForeCastDisplay(weatherData);
weatherData.setMeasurements(80, 65, 30.4f);
weatherData.setMeasurements(82, 70, 29.2f);
weatherData.setMeasurements(78, 90, 29.2f);
}
}
Output:
Forecast: Improving weather on the way!
Current conditions: 80.0F degrees and 65.0% humidity
Forecast: Watch out for cooler, rainy weather
Current conditions: 82.0F degrees and 70.0% humidity
Forecast: More of the same
Current conditions: 78.0F degrees and 90.0% humidity
new
Download