Prog. 2 5 • • • • Prog. 2 Pakete 5 – Paketname – Klassen- oder Objektname – Methoden- oder Variablenname • • Ein Paket ist eine Sammlung von Klassen In Java ist jede Klasse Bestandteil eines Pakets Paketnamen können aus mehreren Teilen bestehen und beliebig tiefe Hierarchien ausdrücken Der Name einer Methode oder Variable besteht aus Die import-Anweisung Die import-Anweisung gibt es in zwei verschiedenen Ausprägungen 1. Mittels import paket.Klasse; wird genau eine Klasse importiert. Alle anderen Klassen des Pakets bleiben unsichtbar • Beispiel: java.lang.Math.sqrt Zwei Möglichkeiten um anzugeben in welchem Paket eine Klasse liegt 2. Mittels import paket.*; können alle Klassen des angegebenen Pakets auf einmal importiert werden – Die Klasse wird über ihren vollen Namen angesprochen • java.util.Date date = new java.util.Date(); • – Am Programmanfang gewünschte Klassen mittels import einbinden • import java.util.*; ... Date date = new Date(); • • Werden Klassen verwendet, ohne zugehörige import-Anweisung (z.B. String oder Object) entstammen sie dem Paket java.lang – Expliziter Import mittels import java.lang.*; ist somit nie nötig 14.05.2009 Prog. 2 5 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 1 14.05.2009 Prog. 2 Die Bedeutung der Paketnamen 5 • Paketnamen bestehen in Java aus mehreren Komponenten, die durch Punkte getrennt sind • Jeder Teil eines mehrstufigen Paketnamens bezeichnet ein Unterverzeichnis auf dem Weg zur gewünschten Klassendatei • • • Eine Klasse aus dem Paket com.sun.image.code.jpeg wird im Unterverzeichnis com/sun/image/code/jpeg gesucht 2 Eigene Pakete erstellen (package) Um eine eigene Klasse einem Paket zuzuordnen, muß am Anfang des Quelltextes, noch vor einer potentiellen import-Anweisung, eine package-Anweisung stehen – Alle Standardpakete und Standarderweiterungen (Bootstrap Classes) werden mittels sun.boot.class.path gefunden. • Nichtstandardpakete werden im aktuellen Verzeichnis und mit Hilfe der Umgebungsvariablen CLASSPATH gesucht Gibt es in einer Quelldatei keine package-Anweisung, gehört die zugehörige Klasse zum Default-Paket – Die Quelldatei wird im aktuellen Verzeichnis abgelegt, kompiliert und eingebunden – Klassen des Default-Pakets können ohne explizite import-Anweisung verwendet werden – Beim Aufruf des Compilers kann der Schalter -classpath gefolgt von einer Liste von Verzeichnisnamen übergeben werden – Compiler-Schalter haben Vorrang gegenüber Umgebungsvariablen FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke Aufbau und Bedeutung der Paketnamen in der package-Anweisung entsprechen dem der import-Anweisung – Der Compiler löst den hierarchischen Namen in eine Kette von Unterverzeichnissen auf, an deren Ende die Quelldatei steht – Die Klassendatei zur Quelldatei wird im gleichen Verzeichnis erstellt – Der Compiler übersetzt eingebundene Quelldateien während der Übersetzung einer Klasse automatisch mit Startverzeichnis für die Suche von Standardpaketen (ab JDK 1.2) 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke • Beispiel: package meinPaket; • Eine Klasse aus dem Paket java.awt.image wird im Unterverzeichnis java/awt/image gesucht • Klassen werden erst dann gesucht, wenn sie benötigt werden (type import on demand) Beispiel: import java.util.*; Date date = new Date(); ... Vector v = new Vector(); – package Anweisung besteht aus dem Schlüsselwort package und dem Namen des Pakets, dem die nachfolgende Klasse zugeordnet werden soll – Beispiele • Beispiel: import java.util.Date; ... Date date = new Date(); java.util.Vector = new java.util.Vector(); 3 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 4 Prog. 2 5 Prog. 2 Eigene Pakete (Beispiel (I)) package ss09; public class KlasseA { public void hallo(){ System.out.println(“Klasse A"); } } 5 • PackageDemo kann übersetzt werden, ohne zuvor die Klassen KlasseA, KlasseB, KlasseC übersetzen zu müssen import ss09.*; import ss09.tools.*; public class PackageDemo { public static void main(String [] args) { (new KlasseA()).hallo(); package ss09; public class KlasseB { public void hallo(){ System.out.println(“Klasse B"); } } • (new KlasseC()).hallo(); } } PackageDemo.java KlasseA.java Prog. 2 5 • – B als public deklariert wurde oder – A und B zum gleichen Paket gehören • • Werden nur Default-Pakete verwendet liegen alle Klassen im selben Paket und es ist egal ob eine Klasse public ist oder nicht (package scoped) Aus unterschiedlichen Paketen können lediglich Klassen eingebunden werden, die public sind – ansonsten bricht der Compiler die Übersetzung mit einer Fehlermeldung ab 14.05.2009 5 PackageExample – findet die Packetverzeichnisse ss09 und ss09/tools PackageDemo.java 14.05.2009 Prog. 2 5 PackageDemo.class ss09 KlasseA.class KlasseA.java KlasseB.java tools KlasseC.class KlasseC.java FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 6 Design-Patterns (Entwurfsmuster) „Each pattern describes a problem which occurs over and over again in our BeispielVerzeichnis class KA { int ka; KA(int ka) this.ka = ka; } } KA.java class KB { int kb; KB(int kb) this.kb = kb; } } KB.java environment, and then describes the core of the solution to that problem in such a way that you can use this solution a million times over, without ever doing it the same way twice“ (Christopher Alexander, Architekt) • Design-Patterns stellen vordefinierte Lösungen für konkrete Programmierprobleme dar (ähnlich wie Datenstrukturen oder Algorithmen, nur auf höherer Abstraktionsebene) • Wichtige Design-Patterns sind • public class PublicTest PublicTest.java { public static void main(String[] args) { KA kA = new KA(10); KB kB = new KB(20); System.out.println(kA.ka); System.out.println(kB.kb); } } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke – erkennt die Verwendung von KlasseA und KlasseC – übersetzt die Klasse PackageDemo tools Das Attribut public Eine Klasse A darf eine Klasse B einbinden, wenn Der Compiler – bindet die .class Dateien ein KlasseB.java FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke Aufruf von javac PackageDemo.java im Verzeichnis PackageExample erzeugt alle notwendigen Dateien – erzeugt benötigte .class-Datei im Verzeichnis der .java-Datei ss09 KlasseC.java 14.05.2009 • – erkennt, welche der benötigten Quellen noch nicht übersetzt sind PackageExample package ss09.tools; public class KlasseC { public void hallo(){ System.out.println(“Klasse C"); } } Eigene Pakete (Beispiel (II)) 7 Erzeugungsmuster Verhaltensmuster – Immutable – Factory – Interface • Factory-Methode – Iterator • Factory-Klasse – Delegate • Abstrakte Factory • • – Singleton Strukturmuster – Visitor – Observer – Composite 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 8 Prog. 2 5 Prog. 2 Singleton (Einzelinstanz) 5 • Ein Singleton (einelementige Menge, Einzelinstanz ) • – ist eine Klasse von der nur ein einziges Objekt erzeugt werden darf – stellt globale Zugriffsmöglichkeit auf das eine Objekt zur Verfügung – instanziert das Objekt automatisch beim ersten Zugriff • Wichtige Designmerkmale einer Singleton-Klasse: – Hat eine statische Membervariable ihres eigenen Typs, in dem die einzige Instanz gespeichert wird – Hat eine statische Methode getInstance, mit der auf die Instanz zugegriffen werden kann – Hat einen privaten parameterlosen Konstruktor (verhindert das Ableiten und das andere Klassen mittels new eine Instanz erzeugen ) • • • Beispiele für Singletons – – – – Druckerspooler Datenbank (Übersetzungstabellen, ...) Fenstermanager ... 14.05.2009 Prog. 2 Immutable (unveränderlich) • Immutable Objekte private static Singleton instance = null; /* Expliziter Konstruktor muss In der nebenstehenden Implementierung hängt das Singleton an einer statische Variablen und wird ebenso wie alle Objekte auf die von ihm verwiesen werden, während der Laufzeit nie gelöscht unbenutzbar gemacht werden! */ private Singleton() {} public static Singleton getInstance() { if(instance == null) { instance = new Singleton(); } return instance; } // Weiter Methoden ... } Singleton s = new Singleton(); // Fehler!!! • Ein Iterator enthält die folgenden beiden Bestandteile: 10 – Eine Methode hasNext public class Immutable • Überprüft ob noch nicht besuchte Elemente vorhanden sind { private int FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke Iterator – Eine Methode next v1; • Liefert das nächste zu untersuchende Element private String[] v2; • Zugehörige Collection-Klasse enthält Methoden wie getAllElements und getKeys mit denen Iteratoren für bestimmte Teilmengen der enthaltenen Objekte angefordert werden können • Klassendiagramm für einen Iterator this.v1 = v1; Wichtige Designmerkmale 14.05.2009 { 5 public final class Immutable */ public Immutable(int v1, String[] v2) { – Alle Membervariablen sind private – Schreibender Zugriff auf Membervariablen nur im Konstruktor/Initialisierer – Lesende Zugriffe verboten, wenn Membervariable ein veränderliches Objekt oder Array ist – Veränderliche Objekte/Arrays, die im Konstruktor übergeben werden, müssen vor der Zuweisung an Membervariablen kopiert werden public class Singleton Durch die Deklaration eines privaten Konstruktors Können keine Instanzen ausserhalb der Klasse erzeugt werden 14.05.2009 Prog. 2 Evtl. als final deklarieren: – Die Klasse String, Wrapper-Klassen • 9 /* Exemplarische Immutable-Implementierung. Beispiele: // Exemplarische Singleton-Implementierung Singleton instance = Singleton.getInstance(); 5 • Singletons können den Zugriff auf statische Variablen kapseln und ihre Instanzierung kontrollieren // Zugriff auf Singleton-Instanz mittels FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke – sind nach ihrer Instanzierung unveränderbar – haben Membervariablen die im Konstruktor oder in Initialisierern gesetzt gesetzt und danach nur noch lesend verwendet werden Singleton // Arrays vor der Zuweisung kopieren! this.v2 = (String[]) v2.clone(); } Collection public int getIntValue() { getElements return v1; erzeugt } public String getStringValue(int index) { return v2[index]; element } liefert Iterator hasNext next } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 11 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 12 Prog. 2 5 Prog. 2 Iterator (Beispiel) interface StringIterator { public boolean hasNext(); public String next(); } 5 public class IteratorExample { static final String[] S={“How“,“are“,“you“}; • Eine Factory – ist ein Hilfsmittel zur Erzeugung von Objekten public static void main(String[] args) { // Erzeugen einer Collection StringArray sArr = new StringArray(S); class StringArray { String[] data; Factory (Fabrik) – wird verwendet, wenn • das Instanzieren eines Objekts mit dem new-Operator alleine nicht möglich oder nicht sinnvoll ist. Gründe: // Elemente mittels while durchlaufen StringIterator it = sArr.getElements(); while(it.hasNext()) { System.out.println(it.next()); } public StringArray(String[] data) { this.data = data; } public StringIterator getElements() { return new StringIterator() { int index = 0; public boolean hasNext() { return index < data.length; } public String next() { return data[index++]; } }; } – Objekt ist schwierig zu konstruieren – Objekt muß vor seiner Verwendung aufwendig konfiguriert werden • die Menge der Klassen, aus denen Objekte generiert werden können dynamisch ist und zur Laufzeit erweitert werden kann // Elemente mittel for durchlaufen for(SringIterator it = sArr.getElements; it.hashNext(); ) { System.out.println(it.next()); } • Die drei wichtigsten Varianten einer Factory sind – Factory-Methoden } – Factory-Klassen } – Abstrakte Factory } 14.05.2009 Prog. 2 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 5 Factory-Methode • Factory-Methoden – rufen den new-Operator auf – führen alle erfoderlichen Konfigurationen durch Klassendiagramm Product createProduct 5 public class Icon { private Icon(){ // Verhindert manuelles Instanzieren } Eine Factory-Klasse ist eine eigenständige Klasse, um (verschiedene) Objekte zu instanzieren • Klassendiagramm public class FunktionFactory { public FunktionFactory(){ // Erzeugen und Konfigurieren der Factory } public Funktion createFromClassFile(String name) { Funktion ret = null; /* Laden der Klassendatei name, prüfen ob sie Funktion implementiert, und gegebenenfalls instanzieren */ return ret; } Factory createProduct • if(name.endsWith(“.gif“)) { erzeugt Product // Erzeugen eines Icons aus jpg-Datei – Es können beliebig viele Instanzen erzeugt werden – Factory-Methode merkt sich nicht ob und wieviel Objekte erzeugt wurden public Funktion createFromPolynom(String expression) { Funktion ret = null; /* Erzeugen eines Funktion-Objekts, aus dem Polynomausdruck expression */ return ret; } – Factory selbst soll austauschbar sein } else if(name.endsWith(“.png“)) { // Erzeugen eines Icons aus png-Datei } – Erzeugung unterschiedlicher Objekte, die lediglich eine gemeinsames Interface implementieren return ret; } } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke Anwendungen – Instanzierung eines Objektes ist extrem aufwändig } else if(name.endsWith(“.jpg“)) { 15 14 Factory-Klasse erzeugt Unterschiede zu Singleton 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke • /* Factory-Methode zum erzeugen eines Objekts der Klasse Icon */ public static Icon loadFromFile(String name) { Icon ret = null; // Erzeugen eines Icons aus gif-Datei • 14.05.2009 Prog. 2 // Eine Klasse mit einer Faktory Methode – sind statische Methoden, die Objekte einer Klasse erzeugen • 13 14.05.2009 } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 16 Prog. 2 5 Prog. 2 Composite (Verbund) • Das Design-Pattern Composite abstrahiert Datenstrukturen um einzelne Objekte zu Baumstrukturen zusammenzusetzten • Beispiele für Baumstrukturen 5 Composite • Ein Composite enthält die folgenden Bestandteile – Ein (oft abstrakte) Basisklasse (Component) • Repräsentiert elementare und zusammengesetzte Objekte (Container) • Stellt einheitliche Schnittstelle für elementare Objekte und Container zur Verfügung – Elementare Objekte – Menüs, Menüpunkte, Untermenüs, ... • Sind alle von der Basisklasse abgeleitet – Verzeichnisse in einem Dateisystem – Mindestens eine Containerklasse – GUI Komponenten • Nimmt eine Menge von Objekten der Basisklasse auf • • Elemente: Buttons, Textfelder, ... Klassendiagramm • Container: Fenster, Unterfenster,... enthalten ebenfalls wieder Elemente AbstractComponent • Anforderungen – Komposition von Objekten zu einer Baumstruktur • wird durch Container ermöglicht Concrete Component 1 – Einheitliche Schnittstelle für elementare Objekte und Container • wird durch eine Basisklasse ermöglicht 14.05.2009 Prog. 2 5 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 17 Prog. 2 Composite (Beispiel) class MenuEntry { protected String name; public MenuEntry(String name) { this.name = name; } public String toString() { return name; } } public class Menu extends MenuEntry { MenuEntry[] ent; int entryCnt; 5 public class CompositeExample { public static void main(String[] args) { Menu filemenu = new Menu(“Datei“,5); filemenu.add(new MenuEntry(“Neu“)); filemenu.add(new MenuEntry(“Laden“)); filemenu.add(new MenuEntry(“Speichern“)); Menu confmenu = new Menu(“Konfig“,3); confmenu.add(new MenuEntry(“Farben“)); confmenu.add(new MenuEntry(“Fenster“)); confmenu.add(new MenuEntry(“Pfade“)); public Menu(String name, int maxElements) { super(name); filemenu.add(confmenu); this.ent = new MenuEntry[maxElements]; filemenu.add(new MenuEntry(“Beenden“)); entryCnt = 0; } Out.println(filemenu); public void add(MenuEntry entry) { ent[entryCnt++] = entry; } } } public String toString() { String ret = “(“; Programm-Ausgabe: for(int i=0; i<entryCnt; ++i) { ret+=(i!=0 ?“,“ : ““)+ent[i].toString(); (Neu,Laden,Speichern,(Farben,Fenster,Pfade),Beenden) } return ret + “)“; } } 14.05.2009 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 19 Concrete Component 2 Container FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 18 Observer (Beobachter) • Ein Observer baut eine Beziehung zwischen einem Subjekt und seinen Beobachtern auf • Bezeichnungen: – Subjekt (Observable) • Objekt, dessen Zustandsänderung für andere Objekte interessant ist • Anderer Objekte (Beobachter) können ihr Interesse registrieren lassen – Beobachter (Observer) • Objekt, dessen Zustand dem Zustand des Subjekts konstistent folgt • Wird benachrichtigt, wenn sich der Zustand von Observables ändert • Hauptanwendungsgebiet – GUI Programmierung • AWT, Swing, ... 14.05.2009 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 20 Prog. 2 Prog. 2 5 Observer • Ein Observer enthält die folgenden Bestandteile: 5 interface Observer { public void update(Subject subject); – Ein Interface Observer } • Definiert eine Methode update, die immer dann gerufen wird, wenn sich der Zustand eines beobachteten Subjekts ändert public void attach(Observer observer) { observers[obCnt++] = observer; } int cnt = 0; • Definiert Methoden zum Registrieren und Deregistrieren von Observern (Zustandsänderung des Subjekts bewirkt bei registrierte Objekten update Aufruf) Subject subject = new Subject(); – Ein konkretes Subjekt public void detach(Observer observer) { for(int i=0; i<obCnt; ++i) { if(observers[i] == observer) { --obCnt; for(;i<obCnt; ++i) observers[i] = observers[i+1]; break; } } } public void attach(Observer observer) { • Von Subject abgeleitet, ruft nach Zustandsänderung fireUpdate auf (Alle registrierten Beobachter werden aufgerufen und können reagieren) subject.attach(observer); } – Ein konkreter Beobachter • Implementiert das Interface Observer • Registriert sich bei Subjekten über deren Zustand er unterrichtet werden möchte • Implementiert update Klassendiagramm class Subject { Observer[] observers = new Observer[5]; int obCnt = 0; class Counter { – Eine Klasse Subject (in java.util die Klasse Observable) • Observer (Beispiel (I)) public void detach(Observer observer) { subject.detach(observer); } Subject <<interface>> Observer public void inc() { if(++cnt %3 == 0) { attach() detach() fireUpdate() update() public void fireUpdate() { for(int i=0; i<obCnt; ++i) observers[i].update(this); } subject.fireUpdate(); } } Concrete Observer registriert sich bei } Concrete Subject } benachrichtigt 14.05.2009 Prog. 2 5 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 21 Prog. 2 Observer (Beispiel (II)) /* Hauptprogramm instanziert ein Count-Objekt, registriert eine lokale anonyme Klasse als • Beobachter */ public class ObserverTest { public static void main(String[] args) { Counter counter = new Counter(); counter.attach( – eine lokale anonyme Klasse als Beobachter registriert, die bei jeder Benachrichtigung eine Meldung ausgibt } while(counter.cnt < 7) { counter.inc(); System.out.println(counter.cnt); } Im Hauptprogramm wird { } ); 14.05.2009 Die Klasse Counter ist konkretes Subjekt, welches bei jedem Aufruf von inc den eingebauten Zähler um eins erhöht und alle registrierten Beobachter informiert, falls der neue Zählerstand durch drei teilbar ist new Observer() System.out.print(“Durch 3 teilbar:“); } 5 – ein Counter-Objekt instanziert public void update(Subject subject) { } • 14.05.2009 • In Java gibt es im Paket java.util die Klasse Observable und das Interface Observer, die das Observer-Pattern implementieren • Die Klasse Observable besitzt folgende Methoden um Änderungen des Objektzustands nach außen hin mitzuteilen – setChanged() /* */ class Erzaehler extends Observable { private String name; – notifyObservers() – notifyObservers() sendet nur dann eine Nachricht an die Zuhörer, wenn das interne Flag gesetzt ist 14.05.2009 Beispiel einer Klasse, die von der Klasse Observable abgeleitet wird um das Observable-Pattern zu realisieren. Achtung: Obwohl Observable auf ‘able‘ endet ist es eine Klasse und kein Interface. public Erzaehler(String name) { this.name = name; } • setChanged() setzt intern ein Flag, das von notifyObservers() abgefragt wird • dies kann auch manuell mittels clearChanged() geschehen 23 22 Die Klasse Observable public void erzaehle(String text) { setChanged(); notifyObservers(text); } – Nach notifyObservers() Aufruf wird das Flag wieder gelöscht Programm-Ausgabe: 1 2 Durch 3 teilbar: 3 4 5 Durch 3 teilbar: 6 7 FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 24 Prog. 2 5 Methodenübersicht von Observable • public Observable() • – Objekt hat dann keine Observer mehr – Fügt den Observer o zur Observermenge des Objekts hinzu • protected void clearChanged() • boolean hasChanged() void notifyObservers(Object arg) – Informiert alle Observer, über Objektänderung • das Objekt nicht verändert wurde • Alle Observer von der letzten Änderung informiert wurden (hashChanged() liefert false) • Schickt Nachricht arg an die Methode update des Interface Observer • Anschließend wird clearChanged() aufgerufen int countObservers() • – Liefert die Anzahl von Observern des Observable-Objekts • void notifyObservers() void deleteObserver(Observer o) • protected void setChanged() Prog. 2 5 – Markiert das Observable-Objekt als geändert FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 25 Observable und Observer (Beispiel) class Erzaehler extends Observable { private String name; public Erzaehler(String name) { this.name = name; } public void erzaehle(String text) { setChanged(); notifyObservers(text); } import java.util.*; public class Party { public static void { Zuhoerer achim = Zuhoerer micha = Erzaehler pitt = main(String[] args) new Zuhoerer(“Achim“); new Zuhoerer(“Micha“); new Erzaehler(“Pitt“); pitt.addObserver(achim); pitt.erzaehle(“Bla, bla, bla“); } class Zuhoerer implements Observer { private String name; public Zuhoerer(String name) { this.name = name; } public void update(Observable o, Object obj) { System.out.print(name + “ hoert \““); System.out.println(obj + “\““); } } 14.05.2009 pitt.addObserver(micha); pitt.erzaehle(“Noch mehr, bla, bla“); pitt.deleteObserver(achim); pitt.erzaehle(“Neues, bla, bla“); } } Programm-Ausgabe: Achim hoert “Bla, bla, bla“ Micha hoert “Noch mehr, bla, bla“ Achim hoert “Noch mehr, bla, bla“ Micha hoert “Neues, bla, bla“ FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke Das Interface Observer Der Sender einer Nachricht (aktives Objekt) ist ein Exemplar der Klasse Observable Soll eine Klasse über Änderungen eines Observable-Objektes informiert werden (passives Objekt), muss sie das Interface Observer implementieren /* */ class Zuhoerer implements Observer { private String name; public Zuhoerer(String name) { this.name = name; } – Objekte, die die Schnittstelle Observer implementieren, implementieren die Methode update(Observabel, Object) 27 – Der zweite Parameter von update ist die mittels notifyObservers() verschickte Nachricht 14.05.2009 Beispiel einer Klasse, die das Interface Observer implementiert. Achtung: Hier ist Observer und nicht Observable das Interface. public void update(Observable o, Object obj) { System.out.print(name + “ hoert \““); System.out.println(obj + “\““); } – update wird bei Änderungen vom Observable-Objekt aufgerufen – Wie notifyObservers(null); – Löscht den Observer o aus der Observermenge des Objekts 14.05.2009 • – Test ob sich das Objekt geändert hat – Zeigt an, dass • • – Löscht Observermenge des Objekts void addObserver(Observer o) • 5 void deleteObservers() – Konstruktor • Prog. 2 } FH-Wiesbaden --- Medieninformatik --- SS 2009 --- Prof. Dr. Ulrich Schwanecke 26