Download Observer Design Pattern

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Pattern recognition wikipedia , lookup

Renormalization group wikipedia , lookup

Eigenstate thermalization hypothesis wikipedia , lookup

Transcript
“Studying software design patterns is an
effective way to learn from the
experience of others”
1
Parties have different ways
of presenting the results.
Presentation
of results
Coupling
Computation
of results
“If the presentation classes and
computation classes are coupled, then can’t
reuse one without dragging along the
other.”
For example, if you wanted to
reuse bar chart code, you would
need to take the computational
class, since they are coupled.
Application runs algorithms on
data, and produces the results:
a, b, and c. How should the
results be communicated to the
interested parties?
2
Description
 Context:
– When associations are created between two classes, the code for the classes
becomes inseparable (coupled):
• Compiling one requires compiling the other.
• Reusing one requires reusing the other.
• Changing one likely requires changing the other.
Consequences of
coupling.
 Issues:
– How do you reduce the interconnection between classes, especially between
classes that belong to different modules or subsystems?
• Removing interconnection implies removing association.
• When interconnection is removed, how can the classes communicate?
You want to minimize the coupling,
but maintain usability.
3
The Observer Pattern
The Problem – Balancing of Forces (Tradeoff)
DataSupplier
DataUser
In order to design the DataSupplier and DataUser for reusability
– separately and independently –
need to remove the association.
But, how can you do this and still maintain usability?
4
Intermediate Solution
(Anti-pattern)
«Observable»
addObserver
notifyObservers
*
«ConcreteObservable»
«interface»
* «Observer»
update
Level 2
Level 1
«ConcreteObserver»
 The user application has two layers of software, Level 2 and Level 1.
 The application adds observers by invoking addObserver in Level 2 for each
observer in Level 1 that is interested in the data of the observerable in Level 1.
 Whenever a Level 1 observable’s data has changed, the observable invokes
notifyObservers in Level 2. The Level 2 method notifyObservers invokes
the update method of each observer that is registered to receive data updates
from the observable.
5
Intermediate Solution
(Anti-pattern)
«Observable»
addObserver
notifyObservers
*
«ConcreteObservable»
«interface»
* «Observer»
update
Level 2
Level 1
«ConcreteObserver»
• The components ConcreteObservable and ConcreteObserver may be reused independently,
since there is no direct association between them:
• In one application, many different Level 1 implementations may exist, and only one level 2 is required. For
example, the following apps require sharing the Level 2 code:
– An app in which a WeatherForecaster has many different kinds of WeatherViewers
– An app in which Mouse events have many different watchers.
– An app in which Keyboard events have many different watchers.
• However, reusing a component requires the software in which it is reused has Level 2.
The problem is that this requires sharing the Level 2 implementation, which would be okay if applied in
the same application, but is problematic when applied across different applications/platforms.
6
The Best Solution
«Observable»
addObserver
notifyObservers
*
«ConcreteObservable»
«interface»
* «Observer»
update
Compiler Layer
Application Layer
«ConcreteObserver»
 Level 2 is implemented by the compiler:
– For example, Java provides Observable and Observer classes:
• i.e., Java implements the Observer Pattern.
– This is a better solution than the previous anti-pattern, but note
that it requires the reusable components use the Java compiler.
• This is reasonable, if the components and different applications are written
in Java.
7
Example: Observable Keyboard
«Observable»
addObserver
notifyObservers
setChanged
Keyboard
* «interface»
«Observer»
*
update
MyApp
Java Compiler Layer
myApp Layer
KBHandler
update
«interface»
Runnable
• MyApp registers KBHandler as an observer of the observable Keyboard.
• The observable Keyboard has a thread that continuously waits for and
receives input from the Standard In (user input).
• When it receives user input, the thread calls setChanged and
notifyObservers.
• Java’s implementation of the Observable invokes the update method of
the KBHandler and passes it the string received from the Observable.
• The update method the KBHandler processes the string in an
application specific way.
8
import java.util.Observable; import java.io.BufferedReader;
import java.io.IOException; import java.io.InputStreamReader;
public class Keyboard extends Observable implements Runnable {
public void run() {
try {
final InputStreamReader isr=new InputStreamReader(System.in);
final BufferedReader br = new BufferedReader(isr);
while (true) {
String response = br.readLine();
setChanged();
notifyObservers(response);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
9
}
import java.util.Observable;
import java.util.Observer; /* this is Event Handler */
public class KBHandler implements Observer {
private String userInput;
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
userInput = (String) arg;
//Do something with the string;
}
}
}
10
myApp CLASS (main METHOD)
public class MyApp {
public static void main(String[] args) {
// create an observable – thread reads from stdin
final Keyboard myKBEventSource = new Keyboard();
// create an observer
final KBHandler myKBHandler= new KBHandler();
// Register the observer to the observable
myKBEventSource.addObserver(myKBHandler);
// starts the event thread
Thread thread = new Thread(myKBEventSource);
thread.start();
}
}
11
• Keyboard class can be reused independently
• To reuse Keyboard, the KBHandler class is not required, since Keyboard has no
association to KBHandler.
• In fact, Keyboard does not even know that KBHandler exists!
• Needs the Observer pattern in Java.
• KBHandler class can be reused independently
• To reuse the KBHandler, the Keyboard class is not required, since KBHandler has
no association to Keyboard.
• In fact, KBHandler does not even know that Keyboard exists!
• Needs the Observer pattern in Java.
• MyApp class cannot be reused independently, since it has associations to
Keyboard and KBHandler.
• However, MyApp shows how to implement Observables and Observers using
Java’s Observer Design Pattern.
12
Apply Observer Design Pattern to
P2.3 Refactored Client
«Observable»
addObserver
notifyObservers
*
«ConcreteObservable»
«interface»
* «Observer»
update
Compiler Layer
Application Layer
«ConcreteObserver»
13
<< TCP/IP network, Data >>
Server
<< TCP/IP network, Connection Request >>
ClientTest
UserCommandHandler
myUI
myClient
handleUserCommand
Client
Client
connectToServer
disconnectFromServer
sendMessageToServer
isConnected
stopThread
setPort
getPort
sendMessageToUI
run
StandardIO
myCommmandHandler
setCommand
getUserInput
display
run
<<interface>>
UserInterface
update(String)
ServerMessageHandler
handleServerMessage()
14
Steps
1. Identify the potential observables and observers in
your application.
2. Redraw the UML class diagram to incorporate the
observables and observers. For the observers,
implement the update method.
3. Perform a reusability analysis.
15