6. Architektur interaktiver Systeme 6.1 Ein Modell, viele Sichten 'The night ist fine', the Walrus said, 'Do you admire the view?' Lewis Carroll T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Schichtenarchitektur Benutzungsoberfläche Window Menu Button (Fachliches) Modell Teammitglied Teambesprechung Ablaufsteuerung Datenhaltung T echnische Universität Dresden Prof. Hußmann Seite 1 Softwaretechnologie Modell und Sicht Sicht Methodenaufrufe => Änderungen Sicht Benachrichtigung über Änderungen Modell Beispiel: Dokumentenansicht, Statusanzeige, Menüpunkte Frage: Wie hält man das Modell unabhängig von den einzelnen Sichten darauf ? T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Das 'Beobachter'-Schema A-Beobachter <<interface>> Observer update update * Beobachtung 1.. * Observable A addObserver deleteObserver setChanged notifyObservers for all observers o do: o.update() T echnische Universität Dresden Prof. Hußmann Seite 2 Softwaretechnologie java.util.Observable, java.util.Observer public class Observable { public void addObserver (Observer o); public void deleteObserver (Observer o); protected void setChanged(); public void notifyObservers (); public void notifyObservers (Object arg); } public interface Observer { public void update (Observable o, Object arg); } Argumente für notifyObservers(): – meist nur Art der Änderung, nicht gesamte Zustandsinformation – Beobachter können normale Methodenaufrufe nutzen, um sich näher zu informieren. T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Grundidee der Observable-Implementierung • java.util.Observable ist vordefiniert, der Programmierer muß also den hier skizzierten Code nicht kennen, sondern nur verwenden • Grundidee der Implementierung zum besseren Verständnis: public class Observable { private Collection observed; public void addObserver (Observer o) { observed.add(o); } public void notifyObservers (Object arg) { Iterator it = observed.iterator(); while (it.hasNext()) { (it.next()).update(this, arg); } } } T echnische Universität Dresden Prof. Hußmann Seite 3 Softwaretechnologie Beispielablauf a: A b1: A-Beobachter b2: A-Beobachter addObserver(b1) addObserver(b2) setChanged() notifyObservers(c) update(c) update(c) T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Java-Beispiel class Teammitglied extends Observable { void teilnahmeSetzen (Teambesprechung b) { teilnahme.add(b); setChanged(); notifyObservers(b); ... } class TeammitglObserver implements Observer { public void update (Observable o, Object arg) { System.out.println ("*** Teammitglied "+o+" nimmt teil an "+arg); } } T echnische Universität Dresden Prof. Hußmann Seite 4 Softwaretechnologie Konstruktor der Klasse Teambesprechung public Teambesprechung (String titel, Hour beginn, int dauer, Teammitglied[] teilnehmer) { // Termin-Konstruktor super(titel, beginn, dauer); // Lokale Repraesentation der Assoziation anlegen this.teilnahme = new HashSet(); for (int i=0; i<teilnehmer.length; i++) this.teilnahme.add(teilnehmer[i]); // Terminkonflikte pruefen if (! abstimmen(beginn, dauer)) System.out.println("Termin bitte verschieben!"); else { // Repr. der Assoziation bei Teammitgliedern anlegen Iterator it = this.teilnahme.iterator(); while (it.hasNext()) ((Teammitglied)it.next()).teilnahmeSetzen(this); } } T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Ablauf des Beispielprogramms public static void main (String argv[]) { ... Teammitglied mm = new Teammitglied("Max Mueller",…); TeammitglObserver tmo = new TeammitglObserver(); mm.addObserver(tmo); Teammitglied es = new Teammitglied("Eva Schmidt",…); Teammitglied fm = new Teammitglied("Fritz Maier",…); ... Teammitglied[] teiln1 = {mm, es}; Teambesprechung tb1 = new Teambesprechung("Besprechung 1",…,teil1); Teammitglied[] teiln2 = {mm, fm}; Teambesprechung tb2 = new Teambesprechung("Besprechung 2",…,teiln2); ... } *** Teammitglied (Name = Max Mueller, Abt. = Abt. A) nimmt teil an Teambesprechung (Name = Besprechung 1) *** Teammitglied (Name = Max Mueller, Abt. = Abt. A) nimmt teil an Teambesprechung (Name = Besprechung 2) T echnische Universität Dresden Prof. Hußmann Seite 5 Softwaretechnologie Vorteile des Beobachter-Schemas • Jede Klasse des Modells definiert lokal, – welche Veränderungen beobachtbar sind (d.h. aktiv der Umwelt mitgeteilt werden) und – wann die Mitteilung erfolgen soll. • Eine beobachtete Klasse – hat keine Information darüber, was die Beobachter konkret tun; – muß nicht geändert werden, wenn sich Beobachter verändern; – muß nicht geändert werden, wenn neue Beobachter dazukommen oder Beobachter wegfallen. • Methodik: – Hinweise auf wichtige Zustandsveränderungen gibt das UMLZustandsdiagramm. T echnische Universität Dresden Prof. Hußmann Softwaretechnologie 5. Architektur interaktiver Systeme 6.2 Ereignisgesteuerter Programmablauf I claim not to have controlled events, but confess plainly that events have controlled me. Abraham Lincoln, 1864 T echnische Universität Dresden Prof. Hußmann Seite 6 Softwaretechnologie Ereignisse • Definition Ein Ereignis ist ein Vorgang in der Umwelt des Softwaresystems von vernachlässigbarer Dauer, der für das System von Bedeutung ist. Eine wichtige Gruppe von Ereignissen sind Benutzerinteraktionen. • Beispiele für Benutzerinteraktions-Ereignisse: – – – – – – – – Drücken eines Knopfs Auswahl eines Menüpunkts Verändern von Text Zeigen auf ein Gebiet Schließen eines Fensters Verbergen eines Fensters Drücken einer Taste Mausklick • Objekte, die Ereignisse beobachten, heißen Listener. T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Ereignis-Klassen • Klassen von Ereignissen in Benutzungsoberflächen: – – – – WindowEvent ActionEvent MouseEvent KeyEvent, ... • Bezogen auf Klassen für Oberflächenelemente (siehe Kapitel 5.3): – – – – Window Frame Button TextField, ... • Zuordnung (Beispiele): – Window (mit Frame) erzeugt WindowEvent » z.B. Betätigung des Schließknopfes – Button erzeugt ActionEvent » bei Betätigung des Knopfes T echnische Universität Dresden Prof. Hußmann Seite 7 Softwaretechnologie Ereignis-Delegation Laufzeit-System betätigt Schließknopf Benutzer f: Frame Quelle vom System neu erzeugt: e: WindowEvent registriert bei Delegation: Aufruf einer Methode von l mit Argument e l: WindowListener Hinweis "für Java-Insider": Hier wird der Einfachheit wegen noch reines AWT verwendet, im nächsten Kapitel wird Swing eingeführt werden. T echnische Universität Dresden Prof. Hußmann Softwaretechnologie java.awt.event.WindowEvent public class WindowEvent extends AWTEvent { ... // Konstruktor, wird vom System aufgerufen public WindowEvent (Window source, int id); // Abfragemöglichkeiten public Window getWindow(); } T echnische Universität Dresden Prof. Hußmann Seite 8 Softwaretechnologie java.awt.event.WindowListener public interface WindowListener extends EventListener { public void windowClosed (WindowEvent ev); public void windowOpened (WindowEvent ev); public void windowIconified (WindowEvent ev); public void windowDeiconified (WindowEvent ev); public void windowActivated (WindowEvent ev); public void windowDeactivated (WindowEvent ev); public void windowClosing (WindowEvent ev); } java.util.EventListener: Basisinterface für alle "Listener" (keine Operationen) T echnische Universität Dresden Prof. Hußmann Softwaretechnologie java.awt.event.ActionEvent, ActionListener public class ActionEvent extends AWTEvent { ... // Konstruktor, wird vom System aufgerufen public ActionEvent (Window source, int id, String command); // Abfragemöglichkeiten public Object getSource (); public String getActionCommand(); ... } public interface ActionListener extends EventListener { public void actionPerformed (ActionEvent ev); } T echnische Universität Dresden Prof. Hußmann Seite 9 Softwaretechnologie WindowListener für Ereignis "Schließen" import java.awt.*; import java.awt.event.*; class WindowCloser implements WindowListener { public void windowClosed (WindowEvent ev) {} public void windowOpened (WindowEvent ev) {} public void windowIconified (WindowEvent ev) {} public void windowDeiconified (WindowEvent ev) {} public void windowActivated (WindowEvent ev) {} public void windowDeactivated (WindowEvent ev) {} public void windowClosing(WindowEvent event) { System.exit(0); } } T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Hauptprogramm für schließbares Fenster import java.awt.*; import java.awt.event.*; class WindowCloser implements WindowListener { ... siehe andere Folie ... } class ExampleFrame extends Frame { public ExampleFrame () { setTitle("untitled"); setSize(150, 50); addWindowListener(new WindowCloser()); setVisible(true); } } class GUI1 { public static void main (String[] argv) { ExampleFrame f = new ExampleFrame();}} T echnische Universität Dresden Prof. Hußmann Seite 10 Softwaretechnologie java.awt.event.WindowAdapter public abstract class WindowAdapter implements WindowListener { public public public public public public public void void void void void void void windowClosed (WindowEvent ev) {} windowOpened (WindowEvent ev) {} windowIconified (WindowEvent ev) {} windowDeiconified (WindowEvent ev) {} windowActivated (WindowEvent ev) {} windowDeactivated (WindowEvent ev) {} windowClosing (WindowEvent ev) {} } T echnische Universität Dresden Prof. Hußmann Softwaretechnologie Vereinfachung 1: WindowAdapter benutzen import java.awt.*; import java.awt.event.*; class WindowCloser extends WindowAdapter { public void windowClosing(WindowEvent event) { System.exit(0); } } class ExampleFrame extends Frame { public ExampleFrame () { setTitle("untitled"); setSize(150, 50); addWindowListener(new WindowCloser()); setVisible(true); } } class GUI1 { public static void main (String[] argv) { ExampleFrame f = new ExampleFrame();}} T echnische Universität Dresden Prof. Hußmann Seite 11 Softwaretechnologie Schließbares Fenster: Klassenstruktur <<interface>> WindowListener Window windowClosing (e: WindowEvent) addWindowListener (l: WindowListener) <<use>> WindowEvent setSize setTitle setVisible WindowAdapter WindowCloser registriert bei T echnische Universität Dresden Frame ExampleFrame Prof. Hußmann Softwaretechnologie Vereinfachung 2: Innere Klasse benutzen import java.awt.*; import java.awt.event.*; class ExampleFrame extends Frame { class WindowCloser extends WindowAdapter { public void windowClosing(WindowEvent event) { System.exit(0); } } public ExampleFrame () { setTitle("untitled"); setSize(150, 50); addWindowListener(new WindowCloser()); setVisible(true); } } class GUI1 { public static void main (String[] argv) { ExampleFrame f = new ExampleFrame();}} T echnische Universität Dresden Prof. Hußmann Seite 12 Softwaretechnologie Vereinfachung 3: Anonyme Klasse benutzen import java.awt.*; import java.awt.event.*; class ExampleFrame extends Frame { public ExampleFrame () { setTitle("untitled"); setSize(150, 50); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent event) { System.exit(0); }}); setVisible(true); } } class GUI1 { public static void main (String[] argv) { ExampleFrame f = new ExampleFrame();}} T echnische Universität Dresden Prof. Hußmann Seite 13 Softwaretechnologie