<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.byte-welt.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AndreUhres</id>
	<title>Byte-Welt Wiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.byte-welt.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=AndreUhres"/>
	<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php/Spezial:Beitr%C3%A4ge/AndreUhres"/>
	<updated>2026-07-07T17:41:50Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Malen_in_AWT_und_Swing&amp;diff=5202</id>
		<title>Malen in AWT und Swing</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Malen_in_AWT_und_Swing&amp;diff=5202"/>
		<updated>2013-01-12T06:34:19Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Malen in AWT und Swing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
=Malen in AWT und Swing=&lt;br /&gt;
Guter Malcode ist der Schlüssel zu einer leistungsfähigen Anwendung.&lt;br /&gt;
&lt;br /&gt;
Von Amy Fowler.&lt;br /&gt;
&lt;br /&gt;
[http://www.oracle.com/technetwork/java/painting-140037.html Copyright 1994-2008 Sun Microsystems, Inc.] &lt;br /&gt;
&lt;br /&gt;
Übersetzung: André Uhres (Ich habe bei Sun die Erlaubnis angefragt, diesen Artikel zu übersetzen und hier zu veröffentlichen)&lt;br /&gt;
&lt;br /&gt;
*HINWEIS vom Übersetzer: Zum Einstieg in das Malen mit Swing ist auch der folgende kurze und praxisorientierte Artikel gut geeignet: [[Malen in Swing Teil 1: der grundlegende Mechanismus]]&lt;br /&gt;
&lt;br /&gt;
In einem graphischen System ist normalerweise ein Fensterdarstellungstoolkit dafür verantwortlich, einen Rahmen zur Verfügung zu stellen, der es relativ einfach macht, auf einer graphischen Benutzerschnittstelle (GUI) die richtigen Bits zur richtigen Zeit darzustellen.&lt;br /&gt;
Sowohl [[AWT]] (abstraktes Fensterdarstellungstoolkit) als auch [[Swing]] liefern solch einen Rahmen. &lt;br /&gt;
Aber die [[API]]s, die ihn verwirklichen, werden von manchen [[Entwickler]]n nicht gut verstanden -- ein Problem, das zu Programmen geführt hat, die nicht so leistungsfähig sind, wie sie sein könnten. &lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt die AWT und Swing Malmechanismen im Einzelnen. Sein Zweck ist, Entwicklern zu helfen, korrekten und leistungsfähigen GUI Malcode zu schreiben. Während der Artikel die allgemeinen Malmechanismen umfaßt (wo und wann man darstellt), erklärt er nicht, wie man die Swing Graphiken APIs benutzt, um korrekte Graphiken darzustellen. Um zu erlernen wie man nette Graphiken macht, besichtigen Sie bitte die [http://docs.oracle.com/javase/tutorial/2d/index.html Java 2D Website].&lt;br /&gt;
&lt;br /&gt;
=Entwicklung des Swing Malsystems=&lt;br /&gt;
&lt;br /&gt;
Als die ursprüngliche AWT API für [[JDK]] 1.0 entwickelt wurde, gab es nur heavyweight Komponenten (&amp;quot;heavyweight&amp;quot; bedeutet, daß die Komponente ihr eigenes undurchlässiges natives Fenster hat). Dies erlaubte es dem AWT, sich voll auf das Maluntersystem der nativen Plattform zu stützen. Dieser Entwurf kümmerte sich um Einzelheiten wie Beschädigungserkennung, Clipberechnung und Z-Einrichtung. &lt;br /&gt;
&lt;br /&gt;
Mit der Einführung der lightweight Komponenten in JDK 1.1 (eine &amp;quot;lightweight&amp;quot; Komponente ist eine, die das native Fenster ihres nächsten heavyweight Vorfahrs wiederverwendet), mußte das AWT das Malen für lightweight Komponenten im gemeinsamen Java Code einführen. Somit gibt es feine Unterschiede bezüglich des Malvorgangs für heavyweight und lightweight Komponenten. Nach dem JDK 1.1, als das Swing Toolkit freigegeben wurde, stellte dieses seine eigenen Malmechanismen vor. In den meisten Fällen ähnelt und beruht der Swing Malmechanismus auf dem AWT. Aber er führt auch einige Unterschiede bezüglich der Mechanismen ein, sowie neue APIs, mit denen die Anwendungen den Malvorgang einfacher anpassen können.&lt;br /&gt;
&lt;br /&gt;
=Malen in AWT=&lt;br /&gt;
&lt;br /&gt;
Zu verstehen, wie die Mal-API von AWT arbeitet, hilft zu erkennen, was einen Malvorgang in einer Fensterdarstellungsumgebung auslöst. In AWT gibt es zwei Arten von Malvorgängen: systemausgelöstes Malen und anwendungsausgelöstes Malen. &lt;br /&gt;
&lt;br /&gt;
==Systemausgelöstes Malen==&lt;br /&gt;
&lt;br /&gt;
In einem systemausgelösten Malvorgang, bittet das System eine Komponente, ihren Inhalt darzustellen, normalerweise aus einem der folgenden Gründe: &lt;br /&gt;
&lt;br /&gt;
* Die Komponente wird zum erstenmal sichtbar auf dem [[Bildschirm]] abgebildet. &lt;br /&gt;
* Die Komponente wird in der Größe verändert.&lt;br /&gt;
* Die Komponente wurde beschädigt und muß repariert werden (zum Beispiel wurde etwas verschoben, das vorher die Komponente verdeckte, und ein vorher verdeckter Teil der Komponente wird sichtbar).&lt;br /&gt;
&lt;br /&gt;
==Anwendungsausgelöstes Malen==&lt;br /&gt;
&lt;br /&gt;
Bei einem anwendungsausgelösten Malvorgang entscheidet die Komponente, daß sie ihren Inhalt aktualisieren muß, weil sich ihr interner [[Zustand]] geändert hat. Beispiel: ein Button erkennt, daß eine [[Maus]]taste betätigt worden ist und stellt fest, daß er einen &amp;quot;niedergedrückten&amp;quot; Button malen muß.&lt;br /&gt;
&lt;br /&gt;
==Die paint Methode==&lt;br /&gt;
&lt;br /&gt;
Ungeachtet dessen, wie ein Malantrag ausgelöst wird, benutzt das AWT einen &amp;quot;callback&amp;quot; (&amp;quot;Wiederholungsbesuch&amp;quot;) Mechanismus zum Zeichnen, und dieser Mechanismus ist derselbe für heavyweight und lightweight Komponenten. Das heißt, daß ein [[Programm]] den Darstellungscode der [[Komponente]] innerhalb einer bestimmten überschriebenen [[Methode]] setzen sollte, und das [[Toolkit]] ruft diese Methode auf, wenn es Zeit ist zu malen. Die zu überschreibende Methode ist in &#039;&#039;&#039;java.awt.Component&#039;&#039;&#039;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;public void paint(Graphics g)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn AWT diese Methode aufruft, ist der Parameter &amp;quot;Graphics g&amp;quot; mit dem passenden Zustand für das Zeichnen auf dieser bestimmten Komponente vorkonfiguriert: &lt;br /&gt;
&lt;br /&gt;
* Die Farbe des Graphics Objektes wird auf die foreground-Eigenschaft der Komponente eingestellt. &lt;br /&gt;
* Die Schriftart des Graphics Objektes wird auf die font-Eigenschaft der Komponente eingestellt. &lt;br /&gt;
* Die &amp;quot;translation&amp;quot; des Graphics Objektes wird so eingestellt, daß die Koordinate (0,0) die obere linke Ecke der Komponente darstellt. &lt;br /&gt;
* Das &amp;quot;clip&amp;quot;-Rechteck des Graphics Objektes wird auf den Bereich der Komponente eingestellt, der neu gezeichnet werden muss. &lt;br /&gt;
&lt;br /&gt;
Programme müssen dieses Graphics Object verwenden (oder ein von ihm abgeleitetes) um die Oberfläche darzustellen. Sie sind frei, den Zustand des Graphics Objektes so zu ändern, wie es benötigt wird.&lt;br /&gt;
Hier ist ein einfaches Beispiel von einem paint callback, der einen gefüllten Kreis innerhalb einer Komponente darstellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void paint(Graphics g) {&lt;br /&gt;
        // Dynamically calculate size information&lt;br /&gt;
        Dimension size = getSize();&lt;br /&gt;
        // diameter&lt;br /&gt;
        int d = Math.min(size.width, size.height); &lt;br /&gt;
        int x = (size.width - d)/2;&lt;br /&gt;
        int y = (size.height - d)/2;&lt;br /&gt;
&lt;br /&gt;
        // draw circle (color already set to foreground)&lt;br /&gt;
        g.fillOval(x, y, d, d);&lt;br /&gt;
        g.setColor(Color.black);&lt;br /&gt;
        g.drawOval(x, y, d, d);&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entwickler, die neu bei AWT sind, werden einen Blick auf das PaintDemo Beispiel werfen wollen, das ein lauffähiges Programmbeispiel liefert, wie man den paint callback in einem AWT Programm verwendet:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/PaintDemo.java PaintDemo]&lt;br /&gt;
&lt;br /&gt;
Im allgemeinen sollten Programme es vermeiden, darstellenden Code an irgendeinen Punkt zu setzen, wo er von außerhalb des Bereichs der paint callback Methode aufgerufen werden könnte. Warum? Weil solcher Code manchmal aufgerufen werden kann, wenn es nicht angebracht ist zu malen -- zum Beispiel bevor die Komponente sichtbar ist oder Zugang zu einem gültigen Graphics Objekt hat. Es wird nicht empfohlen, daß Programme paint() direkt aufrufen. &lt;br /&gt;
&lt;br /&gt;
Um anwendungsausgelöstes Malen zu ermöglichen, liefert das AWT die folgenden &#039;&#039;&#039;java.awt.Component&#039;&#039;&#039; Methoden, damit Programme einen asynchronen Malvorgang anfragen können: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void repaint() &lt;br /&gt;
    public void repaint(long tm) &lt;br /&gt;
    public void repaint(int x, int y, int width, int height) &lt;br /&gt;
    public void repaint(long tm, int x, int y, int width, int height)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der folgende Code zeigt ein einfaches Beispiel von einem MouseListener, der repaint() benutzt, um Updates auf einer theoretischen Taste auszulösen, wenn die Maus gedrückt und losgelassen wird: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;        MouseListener l = new MouseAdapter() {&lt;br /&gt;
            public void mousePressed(MouseEvent e) {&lt;br /&gt;
                MyButton b = (MyButton)e.getSource();&lt;br /&gt;
                b.setSelected(true);&lt;br /&gt;
                b.repaint();            &lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            public void mouseReleased(MouseEvent e) {&lt;br /&gt;
                MyButton b = (MyButton)e.getSource();&lt;br /&gt;
                b.setSelected(false);&lt;br /&gt;
                b.repaint();            &lt;br /&gt;
            }&lt;br /&gt;
        };&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Komponenten, die komplizierte Darstellungen ausgeben, sollten repaint() mit den Argumenten aufrufen, welche nur den Bereich definieren, der eine Aktualisierung erfordert. Es ist ein allgemeiner Fehler, immer die keine-Argumente Version zu benutzen, die immer die gesamte Komponente neu zeichnet, was häufig zu nicht notwendigen Malverarbeitungen führt. &lt;br /&gt;
&lt;br /&gt;
===paint() gegen update()===&lt;br /&gt;
Warum unterscheiden wir zwischen systemausgelöstem und anwendungsausgelöstem Malen? Weil AWT jeden dieser Fälle etwas anders für heavyweight Komponenten behandelt (der lightweight Fall wird später besprochen), was leider eine Quelle großer Verwirrung ist. &lt;br /&gt;
&lt;br /&gt;
Für heavyweight Komponenten geschehen diese zwei Arten des Zeichnens in zwei unterschiedlichen Wegen, abhängig davon, ob ein Malvorgang systemausgelöst oder anwendungsausgelöst ist.&lt;br /&gt;
&lt;br /&gt;
====systemausgelöstes Malen====&lt;br /&gt;
dies ist, wie ein systemausgelöster Malvorgang stattfindet: &lt;br /&gt;
&lt;br /&gt;
# Das AWT stellt fest, daß entweder ein Teil oder die ganze Komponente gemalt werden muß. &lt;br /&gt;
# Das AWT veranlasst den Event Dispatch Thread, paint() auf der Komponente aufzurufen.&lt;br /&gt;
&lt;br /&gt;
====anwendungsausgelöstes Malen====&lt;br /&gt;
Ein anwendungsausgelöster Malvorgang findet wie folgt statt: &lt;br /&gt;
&lt;br /&gt;
# Das Programm stellt fest, daß entweder ein Teil oder die ganze Komponente in Erwiderung auf eine interne Zustandsänderung neu gezeichnet werden muß. &lt;br /&gt;
# Das Programm ruft repaint() auf der Komponente auf, was einen asynchronen Antrag zum AWT registriert, daß diese Komponente neu gezeichnet werden muß. &lt;br /&gt;
# Das AWT veranlasst den Event Dispatch Thread, ein update() auf der Komponente aufzurufen. ANMERKUNG: Erfolgen mehrfache repaint() Aufrufe auf einer Komponente bevor der erste Antrag verarbeitet wird, können die mehrfachen Anträge zu einem einzigen Aufruf von update() zusammengefasst werden. Der Algorithmus für die Bestimmung, wann mehrfache Anträge zusammengefasst werden sollten, ist Implementierungsabhängig. Wenn mehrfache Anträge zusammengefasst werden, ist das resultierende Updaterechteck gleich der Vereinigung der Rechtecke, die in den zusammengefassten Anträgen enthalten sind. &lt;br /&gt;
# Wenn die Komponente nicht update() überschreibt, löscht die Default-Implementierung von update() den Hintergrund der Komponente (wenn es nicht eine lightweight Komponente ist) und ruft einfach paint() auf. &lt;br /&gt;
&lt;br /&gt;
Da bei der Default-Implementierung das abschließende Resultat dasselbe ist wie bei paint(), verstehen viele Leute den Zweck einer unterschiedlichen update() Methode nicht. Während es zutreffend ist, daß die Default-Implementierung von update() die paint() aufruft, ermöglicht dieser &amp;quot;Updatehaken&amp;quot; einem Programm, den anwendungsausgelösten Malvorgang anders anzufassen, wenn es gewünscht wird. Ein Programm muß annehmen, daß ein Aufruf von paint() andeutet, daß der Bereich, der durch das Cliprechteck vom Graphics definiert wird, &amp;quot;beschädigt&amp;quot; ist und vollständig neu gezeichnet werden muß, gleichwohl ein Aufruf von update() dieses nicht andeutet, was einem Programm ermöglicht, zusätzliches Zeichnen zu tun. &lt;br /&gt;
&lt;br /&gt;
Zusätzliches Zeichnen (&amp;quot;incremental painting&amp;quot;) ist nützlich, wenn ein Programm die zusätzliche Darstellung über die vorhandenen Teilstücke dieser Komponente überlagern möchte. Das UpdateDemo Beispiel zeigt ein Programm, das Nutzen aus dem Verwenden von update() zieht, um zusätzliches Zeichnen zu tun:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/UpdateDemo.java UpdateDemo]&lt;br /&gt;
&lt;br /&gt;
In Wahrheit braucht die Mehrheit der GUI Komponenten kein zusätzliches Zeichnen zu tun. So können die meisten Programme die update() Methode ignorieren und einfach paint() überschreiben, um die Komponente in ihrem gegenwärtigen Zustand darzustellen. Das heißt, daß die systemausgelöste und anwendungsausgelöste Darstellung im Wesentlichen für die meisten Implementierungen gleichbedeutend ist.&lt;br /&gt;
&lt;br /&gt;
==Das Malen und die lightweight Komponenten ==&lt;br /&gt;
Von der Perspektive des Anwendungsentwicklers, ist die Mal-API im Allgemeinen dieselbe für lightweight und heavyweight Komponenten (das heißt, er überschreibt paint() und ruft repaint() auf, um Updates auszulösen). Jedoch seit AWTs lightweight Komponentenrahmen völlig im allgemeinen [[Java]] Code geschrieben wurde, sind dort einige subtile Unterschiede bezüglich der Weise, wie der Mechanismus für lightweight Komponenten implementiert wird. &lt;br /&gt;
&lt;br /&gt;
===Wie lightweight Komponenten gemalt werden===&lt;br /&gt;
Damit eine lightweight Komponente besteht, benötigt sie einen heavyweight Vorfahr in der Containerhierarchie, um einen Platz zum Malen zu haben. Wenn diesem heavyweight Vorfahr gesagt wird, sein Fenster zu malen, muß er den Malaufruf übersetzen in Malaufrufe an alle seine lightweight Nachkommen. Dies wird durch die paint() Methode von &#039;&#039;&#039;java.awt.Container&#039;&#039;&#039; verarbeitet, welche paint() auf irgendwelchen seiner sichtbaren lightweight Kinder aufruft, die sich mit dem zu malenden Rechteck überschneiden. So ist es für alle Containerunterklassen (lighweight oder heavyweight), welche paint() überschreiben, notwendig, folgendes zu tun: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public class MyContainer extends Container {&lt;br /&gt;
        public void paint(Graphics g) {&lt;br /&gt;
	    // paint my contents first...&lt;br /&gt;
	    // then, make sure lightweight children paint&lt;br /&gt;
	    super.paint(g); &lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn der Aufruf von super.paint() fehlt, dann werden die lightweight Nachkommen des Containers nicht dargestellt (ein sehr verbreitetes Problem als JDK 1.1 die lightweight Komponenten einführte). &lt;br /&gt;
&lt;br /&gt;
Es ist nützlich anzumerken, daß die Default-Implementierung von Container.update() nicht die Rekursion verwendet, um update() oder paint() auf lightweight Nachkommen aufzurufen. Das heißt, daß irgendeine heavyweight Containerunterklasse, die update() benutzt, um zusätzlichen Zeichnen zu tun, sichergehen muß, daß lightweight Nachkommen wenn nötig rekursiv neu gezeichnet werden. Glücklicherweise benötigen wenige heavyweight Container zusätzliches Zeichnen, also beeinflußt diese Frage die meisten Programme nicht.&lt;br /&gt;
&lt;br /&gt;
===lightweight und systemausgelöstes Malen ===&lt;br /&gt;
Der lightweight Rahmencode, der das Fensterdarstellungsverhalten für lightweight Komponenten einführt (sichtbar machen, verstecken, bewegen, die Größe neu bestimmen, usw..), ist völlig in Java geschrieben. Innerhalb der Java Implementierung dieser Funktionen, muß das AWT häufig verschiedenen lightweight Komponenten ausdrücklich erklären, sich  zu malen (im Wesentlichen systemausgelöstes Malen, obwohl es nicht mehr vom nativen System ausgeht). Jedoch benutzt der lightweight Rahmen &#039;&#039;&#039;repaint()&#039;&#039;&#039;, um Komponenten zu erklären, sich zu malen, was einen Aufruf von update() anstatt eines Direktaufrufs von paint() ergibt, wie wir oben gesehen haben. Folglich kann systemausgelöstes Zeichnen für lightweight Komponenten zwei Wegen folgen: &lt;br /&gt;
&lt;br /&gt;
* Der systemausgelöste Malantrag entsteht im nativen System (d.h. der heavyweight Vorfahr der lightweight Komponente wird zum ersten Mal sichtbar), was einen Direktaufruf von paint() ergibt. &lt;br /&gt;
* Der systemausgelöste Malantrag entsteht im lightweight Rahmen (d.h., die Größe der lightweight Komponente wird neu bestimmt), was einen Aufruf von update() ergibt, der in der Default-Implementierung an paint() weitergeleitet wird. &lt;br /&gt;
&lt;br /&gt;
Dies bedeutet, daß es für lightweight Komponenten &#039;&#039;&#039;keine reale Unterscheidung zwischen update() und paint() gibt&#039;&#039;&#039;, was weiter bedeutet, daß die zusätzliche Zeichnentechnik (incremental painting) nicht für lightweight Komponenten verwendet werden sollte.&lt;br /&gt;
&lt;br /&gt;
===lightweight und Transparenz===&lt;br /&gt;
Da lightweight Komponenten den Bildschirmplatz eines heavyweight Vorfahrs &amp;quot;borgen&amp;quot;, unterstützen sie die Eigenschaft der Transparenz. Dies funktioniert, weil lightweight Komponenten von hinten nach vorne gemalt werden und folglich, wenn eine lightweight Komponente einige oder all ihre Bits unbemalt läßt, die dahinterliegende Komponente &amp;quot;durchscheint&amp;quot;.  Dies ist auch der Grund, warum die Default-Implementierung von update() den Hintergrund nicht löscht, wenn die Komponente lightweight ist. &lt;br /&gt;
&lt;br /&gt;
Das LightweightDemo Programmbeispiel zeigt die Transparenzeigenschaft der lightweight Komponenten:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/LightweightDemo.java LightweightDemo]&lt;br /&gt;
&lt;br /&gt;
==Das &amp;quot;intelligente&amp;quot; Malen==&lt;br /&gt;
Während das AWT versucht, den Prozeß der Darstellung der Komponenten so leistungsfähig wie möglich zu machen, kann die paint() Implementierung einer Komponente selbst eine bedeutende Auswirkung auf die gesamte Leistung haben. Zwei Schlüsselbereiche, die diesen Prozeß beeinflussen können, sind: &lt;br /&gt;
&lt;br /&gt;
* Die Clipinformationen verwenden, um den Bereich, der dargestellt wird, einzuschränken.&lt;br /&gt;
* Internes Wissen über das Layout verwenden, um den Bereich, welche Kinder gemalt werden, einzuschränken (nur lightweight). &lt;br /&gt;
&lt;br /&gt;
Wenn deine Komponente einfach ist -- zum Beispiel, wenn es eine Drucktaste ist -- dann ist sie die Mühe nicht wert, die Darstellung zu bearbeiten, um nur den Teil zu malen, der das Cliprechteck überschneidet; es ist vorzuziehend, die gesamte Komponente zu malen und die Graphics passend einschränken zu lassen. Wenn du jedoch eine Komponente mit komplizierter Ausgabe erzeugt hast, wie eine Textkomponente, dann ist es notwendig, daß dein Code die Clipinformationen gebraucht, um den Umfang der Darstellung einzuschränken.&lt;br /&gt;
&lt;br /&gt;
Weiter, wenn du einen komplizierten lightweight Container schreibst, der zahlreiche Komponenten beherbergt, wo der Container und/oder sein Layoutmanager Informationen über das Layout hat, dann ist er es wert dieses Layoutwissen zu verwenden, um intelligenter in der Bestimmung zu sein, welche der Kinder gemalt werden müssen. Die Default-Implementierung von Container.paint() schaut einfach der Reihe nach durch die Kinder und prüft die Sichtbarkeit und Überschneidung -- ein Vorgang, der mit bestimmten Layouts unnötigerweise aufwendig sein kann. Zum Beispiel, wenn ein Container die Komponenten in einem Rasterfeld 100x100 auslegt, dann könnte diese Rasterfeldinformation verwendet werden, schneller festzustellen, welche von jenen 10000 Komponenten das Cliptechteck überschneiden und wirklich gemalt werden müssen.&lt;br /&gt;
&lt;br /&gt;
==AWT Malrichtlinien ==&lt;br /&gt;
Das AWT stellt eine einfache callback API für das Malen von Komponenten zur Verfügung. Wenn du sie verwendest, treffen die folgenden Richtlinien zu: &lt;br /&gt;
&lt;br /&gt;
# Für die meisten Programme sollte aller Malcode innerhalb des Bereichs der paint() Methode der Komponente gesetzt werden. &lt;br /&gt;
# Programme können einen zukünftigen Aufruf von paint() auslösen, indem sie repaint() aufrufen, aber sie sollten nicht paint() direkt aufrufen. &lt;br /&gt;
# Bei Komponenten mit komplizierter Ausgabe, sollte repaint() mit Argumenten aufgerufen werden, die nur das Rechteck definieren, das aktualisieren muß, anstatt der keine-Argumente Version, die die gesamte Komponente veranlasst neu gezeichnet zu werden. &lt;br /&gt;
# Da ein Aufruf von repaint() zuerst einen Aufruf von update() ergibt, der in der Default-Implementierung an paint() weitergeleitet wird, können heavyweight Komponenten update() überschreiben, um zusätzliches Zeichnen (incremental painting) zu tun, wenn es gewünscht wird (lightweight Komponenten unterstützen nicht das zusätzliche Zeichnen).&lt;br /&gt;
# Erweiterungen von java.awt.Container, die paint() überschreiben, sollten immer super.paint() aufrufen, um sicherzustellen, dass die Kinder gemalt werden. &lt;br /&gt;
# Komponenten mit komplizierter Ausgabe sollten intelligenten Gebrauch vom Cliprechteck machen, um den Malvorgang auf den Bereich zu beschränken, der sich mit dem Clipbereich überschneidet.&lt;br /&gt;
&lt;br /&gt;
=Malen in Swing=&lt;br /&gt;
Swing beginnt mit AWTs grundlegendem Malmodell und erweitert es, um die Leistung zu maximieren und die Erweiterbarkeit zu verbessern. Wie AWT, so unterstützt auch Swing den Malcallback und den Gebrauch von repaint(), um Updates auszulösen. Zusätzlich gibt Swing eingebaute Unterstützung für Doppelpufferung sowie Änderungen, um die zusätzliche Swing Struktur zu unterstützen (wie Ränder und der UI Delegate). Und schließlich stellt Swing die RepaintManager API für jene Programme zur Verfügung, die den Malmechanismus weiter anpassen möchten.&lt;br /&gt;
&lt;br /&gt;
==Unterstützung für Doppelpufferung ==&lt;br /&gt;
Eine der bemerkenswertesten Eigenschaften von Swing ist, daß es die Unterstützung für Doppelpufferung direkt ins Toolkit einbaut. Das geschieht durch die Bereitstellung der &amp;quot;doubleBuffered&amp;quot; Eigenschaft in &#039;&#039;&#039;javax.swing.JComponent: &lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isDoubleBuffered()&lt;br /&gt;
    public void setDoubleBuffered(boolean o)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Doppelpufferung von Swing benutzt einen einzigen offscreen Puffer pro Containerhierarchie (normalerweise einen pro Fenster) wo die Doppelpufferung eingeschaltet worden ist. Obgleich diese Eigenschaft pro Komponente eingeschaltet werden kann, ergibt ihre Einschaltung in einem bestimmten Container den Effekt, dass alle lightweight Komponenten darunter in dem offscreen Puffer dargestellt werden, unabhängig davon wie die individuelle &amp;quot;doubleBuffered&amp;quot; Eigenschaft eingestellt ist.&lt;br /&gt;
&lt;br /&gt;
Der Default-Wert dieser Eigenschaft ist bei allen Swingkomponenten auf &amp;quot;true&amp;quot; gesetzt. Aber die Einstellung, die wirklich zählt, ist in JRootPane, weil diese Einstellung effektiv Doppelpufferung für alles darunter einschaltet. In den meisten Fällen brauchen Swingprogramme nichts zu tun in Bezug auf Doppelpufferung, ausgenommen, zu entscheiden, ob sie ein- oder ausgeschaltet sein sollte (und für eine flackerfreie GUI wirst du wünschen, dass sie eingeschaltet ist!). Swing stellt sicher, daß die passende Art des Graphics Objektes (offscreen Bild Graphics für Doppelpufferung, sonst die original Graphics) der  Komponente übergeben wird, so braucht die Komponente lediglich mit ihm zu zeichnen. Dieser Mechanismus wird später in diesem Artikel ausführlicher erklärt (im Abschnitt über die Malverarbeitung).&lt;br /&gt;
&lt;br /&gt;
==Zusätzliche Maleigenschaften ==&lt;br /&gt;
Swing stellt einige zusätzliche Eigenschaften von JComponent vor, um die Leistungsfähigkeit der internen Malalgorithmen zu verbessern. Diese Eigenschaften wurden eingeführt, um sich mit den folgenden zwei Fragen zu beschäftigen, die das Zeichnen von lightweight Komponenten zu einem kostspieligen Vorgang machen können: &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Transparenz&#039;&#039;&#039;: Wenn eine lightweight Komponente gemalt wird, ist es möglich, daß die Komponente nicht alle ihre Bits malt, wenn sie teilweise oder ganz transparent ist; das heißt, daß, wann immer sie neu gezeichnet wird, das was dahinter liegt zuerst neu gezeichnet werden muss. Das erfordert vom System, die Containerhierarchie hinaufzugehen um den ersten zugrundeliegenden heavyweight Vorfahr zu finden, von dem der hinten-nach-vorne Malvorgang ausgehen soll. &lt;br /&gt;
* &#039;&#039;&#039;Überlappende Komponenten&#039;&#039;&#039;: Wenn eine lightweight Komponente gemalt wird, ist es möglich, daß irgendeine andere lightweight Komponente sie teilweise verdeckt; das heißt, daß, wann immer die ursprüngliche lightweight Komponente gemalt wird, alle möglichen Komponenten, die die ursprüngliche Komponente überdecken (wo das Cliprechteck sich mit dem überlappenden Bereich schneidet), auch teilweise neu gezeichnet werden müssen. Dies erfordert vom System, bei jedem Malvorgang viel von der Containerhierarchie zu durchqueren und auf überlappende Komponenten zu überprüfen. &lt;br /&gt;
&lt;br /&gt;
===Die Opazität===&lt;br /&gt;
Um im Fall von undurchlässigen Komponenten die Leistung zu verbessern, fügt Swing eine &amp;quot;opaque&amp;quot; Lese-Schreibeigenschaft zu javax.swing.JComponent hinzu: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isOpaque()&lt;br /&gt;
    public void setOpaque(boolean o)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Einstellungen sind: &lt;br /&gt;
&lt;br /&gt;
*true: Die Komponente ist damit einverstanden, alle ihre Bits zu malen, die innerhalb ihrer rechteckigen Grenzen enthalten sind.&lt;br /&gt;
*false: Der Komponente gibt keine Garantien über das Malen aller Bits innerhalb ihrer rechteckigen Grenzen. &lt;br /&gt;
&lt;br /&gt;
Die &amp;quot;opaque&amp;quot; Eigenschaft läßt das Malsystem von Swing ermitteln, ob ein repaint Antrag auf einer bestimmten Komponente zusätzliche repaint Anträge der dahinter liegenden Vorfahren erfordert oder nicht. Der Default-Wert der &amp;quot;opaque&amp;quot; Eigenschaft für jede standard Swingkomponente wird durch das gegenwärtige Look and Feel UI Objekt eingestellt. Der Wert ist für die meisten Komponenten &amp;quot;true&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Einer der allgemeinsten Fehler, die Komponentenimplementierungen machen, ist, daß sie die &amp;quot;opaque&amp;quot; Eigenschaft auf &amp;quot;true&amp;quot; belassen, und dennoch den Bereich nicht vollständig darstellen, der durch ihre Grenzen definiert ist, was gelegentliche Unreinheiten in den nicht dargestellten Bereichen ergibt. Wenn eine Komponente entworfen wird, sollte sorgfältig überlegt werden, wie die &amp;quot;opaque&amp;quot; Eigenschaft zu behandeln ist, sowohl um sicherzustellen, daß Transparenz klug benutzt wird, da sie mehr Darstellungszeit kostet, und daß die Übereinkunft mit dem Malsystem eingehalten wird. &lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &amp;quot;opaque&amp;quot; Eigenschaft wird häufig mißverstanden. Manchmal wird sie verstanden als &amp;quot;den Hintergrund der Komponente transparent machen&amp;quot;. Jedoch ist dies nicht die strenge Deutung der Opazität in Swing. Einige Komponenten, wie eine Drucktaste, können die &amp;quot;opaque&amp;quot; Eigenschaft auf false setzen, um der Komponente eine nicht-rechteckige Form zu geben oder Raum um die Komponente herum zu behalten für vorübergehende Sichtbarmachungen, wie eine Fokusanzeige. In diesen Fällen ist die Komponente nicht opaque, aber der Hauptteil seines Hintergrundes wird dennoch ganz ausgefüllt!&lt;br /&gt;
&lt;br /&gt;
Wie vorher definiert, ist die &amp;quot;opaque&amp;quot; Eigenschaft hauptsächlich ein Vertrag mit dem Repaintsystem. Wenn eine Komponente auch die &amp;quot;opaque&amp;quot; Eigenschaft benutzt, um zu definieren, wie Transparenz an den Sichtbarmachungen einer Komponente angewendet wird, dann sollte dieser Gebrauch von der Eigenschaft dokumentiert werden. (es kann für einige Komponenten vorzuziehen sein, zusätzliche Eigenschaften zu definieren, um die Sichtaspekte davon zu steuern, wie Transparenz angewendet wird. Z.B. hat javax.swing.AbstractButton die ContentAreaFilled Eigenschaft zu diesem Zweck.)&lt;br /&gt;
&lt;br /&gt;
Eine andere Frage, die eine Anmerkung wert ist, ist wie sich Opazität auf die Randeigenschaft einer Swingkomponente bezieht. Der Bereich, der durch ein Randobjekt auf einer Komponente dargestellt wird, wird noch als ein Teil der Geometrie dieser Komponente betrachtet. Das heißt, daß, wenn eine Komponente &amp;quot;opaque&amp;quot; ist, sie immer noch für das Füllen des Bereichs verantwortlich ist, der durch den Rand besetzt wird. (der Rand überlagert dann einfach seine Darstellung über die undurchlässige Komponente). &lt;br /&gt;
&lt;br /&gt;
Wenn eine dahinter liegende Komponente durch den Randbereich einer Komponente durchscheinen soll -- das heißt, wenn der Rand Transparenz unterstützt indem isBorderOpaque() &amp;quot;false&amp;quot; zurückgibt (z.B. EmptyBorder oder LineBorder mit roundedCorners) -- dann, muß die Komponente sich selbst auch als nicht opaque definieren und sicherstellen dass sie den Randbereich nicht übermalt.&lt;br /&gt;
&lt;br /&gt;
Siehe auch: http://forum.java.sun.com/thread.jspa?messageID=10329261&amp;amp;start=1&lt;br /&gt;
&lt;br /&gt;
===&amp;quot;optimiert&amp;quot; zeichnen===&lt;br /&gt;
Die Frage des Zeichnens von überlappenden Komponenten ist heikler. Selbst wenn keiner der direkten Geschwister einer Komponente diese überdeckt, ist es immer möglich, daß ein Nichtvorfahr Verwandter (wie ein &amp;quot;Vetter&amp;quot; oder &amp;quot;Tante&amp;quot;) sie verdecken könnte. In solch einem Fall könnte das repaint einer einzelnen Komponente innerhalb einer komplizierten Hierarchie eine Menge Treewalking erfordern, um &#039;korrektes&#039; Zeichnen sicherzustellen. Um unnötiges Durchqueren zu verringern, fügt Swing die read-only Eigenschaft &amp;quot;isOptimizedDrawingEnabled&amp;quot; zu javax.swing.JComponent hinzu: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isOptimizedDrawingEnabled()&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
die Einstellungen sind: &lt;br /&gt;
&lt;br /&gt;
* true: Die Komponente zeigt an, daß keine seiner direkten Kinder sich überlappen.&lt;br /&gt;
* false: Die Komponente gibt keine Garantie, ob seine direkten Kinder sich überlappen oder nicht.&lt;br /&gt;
&lt;br /&gt;
Indem es die Eigenschaft &amp;quot;isOptimizedDrawingEnabled&amp;quot; überprüft, kann Swing schnell seine Suche nach überlappenden Komponenten zur repaint Zeit eingrenzen.&lt;br /&gt;
&lt;br /&gt;
Da &amp;quot;isOptimizedDrawingEnabled&amp;quot; eine read-only Eigenschaft ist, ist also der einzige Weg, wie Komponenten den Default-Wert ändern können, die Klasse zu erweitern und diese Methode zu überschreiben, um den gewünschten Wert zurückzugeben. Alle standard Swingkomponenten geben &amp;quot;true&amp;quot; für diese Eigenschaft zurück, außer JLayeredPane, JDesktopPane und JViewPort. Wenn wir also z.B. ein JPanel mit einem Layout haben, das überlappende Komponenten zulässt (wie &amp;quot;OverlayLayout&amp;quot;), dann ist es gewöhnlich notwendig, JPanel zu erweitern und isOptimizedDrawingEnabled() zu überschreiben, um &amp;quot;false&amp;quot; zurückzugeben.&lt;br /&gt;
&lt;br /&gt;
==Die Malmethoden ==&lt;br /&gt;
Die Richtlinien, die auf AWTs lightweight Komponenten zutreffen, treffen auch auf Swingkomponenten zu -- zum Beispiel wird paint() aufgerufen, wenn es Zeit ist darzustellen -- außer daß Swing den paint() Aufruf in drei verschiedene Methoden unterteilt, die in folgender Reihenfolge aufgerufen werden: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    protected void paintComponent(Graphics g)&lt;br /&gt;
    protected void paintBorder(Graphics g)&lt;br /&gt;
    protected void paintChildren(Graphics g)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Swingprogramme sollten &#039;&#039;&#039;paintComponent()&#039;&#039;&#039; anstelle von paint() überschreiben. Obgleich die API es erlaubt, gibt es im Allgemeinen keinen Grund paintBorder() oder paintChildren() zu überschreiben (und wenn du es tust, sei dir sicher was du tust!). Dies macht es den Programmen einfacher, nur den Teil des Zeichnens zu überschreiben, den sie erweitern müssen. Z.B. löst dies das AWT Problem, das vorher erwähnt wurde, wo die Unterlassung, super.paint() aufzurufen alle lightweight Kinder am Erscheinen hinderte. &lt;br /&gt;
&lt;br /&gt;
Das SwingPaintDemo Programmbeispiel zeigt den einfachen Gebrauch der paintComponent() callback Methode von Swing:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/SwingPaintDemo.java SwingPaintDemo]&lt;br /&gt;
&lt;br /&gt;
===Das Malen und der UI Delegate ===&lt;br /&gt;
Die meisten standard Swingkomponenten haben ihren Look and Feel implementiert durch getrennte look-and-feel Objekte (genannt &amp;quot;UI Beauftragte&amp;quot;), für die steckbare Look and Feel Eigenschaft von Swing. Das heißt, daß das meiste oder das ganze Zeichnen der standard Komponenten dem UI Delegate übergeben wird und dies geschieht folgendermaßen: &lt;br /&gt;
&lt;br /&gt;
# paint() ruft paintComponent() auf. &lt;br /&gt;
# Wenn die &amp;quot;ui&amp;quot; Eigenschaft nicht &amp;quot;null&amp;quot; ist, ruft paintComponent() ui.update() auf. &lt;br /&gt;
# Wenn die &amp;quot;opaque&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist, füllt ui.update() den Hintergrund der Komponente mit der Hintergrundfarbe und ruft ui.paint() auf. &lt;br /&gt;
# ui.paint() stellt den Inhalt der Komponente dar. &lt;br /&gt;
&lt;br /&gt;
Das heißt, daß Unterklassen von Swingkomponenten, die einen UI Delegate haben (im Gegensatz zu direkten Unterklassen von JComponent), super.paintComponent() innerhalb ihrer paintComponent Überschreibung aufrufen sollten: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public class MyPanel extends JPanel {&lt;br /&gt;
        protected void paintComponent(Graphics g) {&lt;br /&gt;
	    // Let UI delegate paint first &lt;br /&gt;
	    // (including background filling, if I&#039;m opaque)&lt;br /&gt;
	    super.paintComponent(g); &lt;br /&gt;
	    // paint my contents next....&lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn aus irgendeinem Grund die Erweiterung der Komponente nicht zulassen möchte, daß der UI Delegate  malt (wenn sie zum Beispiel die sichtbaren Elemente der Komponente vollständig ersetzt), kann sie den Aufruf von super.paintComponent() weglassen, aber sie ist dann für das Ausfüllen ihres eigenen Hintergrundes verantwortlich, wenn die &amp;quot;opaque&amp;quot; Eigenschaft &amp;quot;true&amp;quot; ist, wie im Abschnitt über die &amp;quot;opaque&amp;quot; Eigenschaft besprochen wurde.&lt;br /&gt;
&lt;br /&gt;
==Malverarbeitung ==&lt;br /&gt;
Swing verarbeitet &amp;quot;repaint&amp;quot; Anträge in einer etwas anderen Weise als AWT, obgleich das Resultat für den Anwendungsprogrammierer im Wesentlichen dasselbe ist -- paint() wird aufgerufen. Swing tut dies, um seine RepaintManager API zu unterstützen (wird später besprochen), sowie zur Verbesserung der Malleistung. In Swing kann das Malen zwei Wegen folgen, wie unten beschrieben: &lt;br /&gt;
&lt;br /&gt;
(a) Der Malantrag entsteht im ersten heavyweight Vorfahr (normalerweise JFrame, JDialog, JWindow oder JApplet): &lt;br /&gt;
&lt;br /&gt;
# der &amp;quot;event dispatching thread&amp;quot; ruft paint() für diesen Vorfahr auf, &lt;br /&gt;
# die Default-Implementierung von Container.paint() ruft rekursiv paint() auf allen lightweight Nachkommen auf, &lt;br /&gt;
# wenn die erste Swingkomponente erreicht wird, macht die Default-Implementierung von &#039;&#039;&#039;JComponent.paint()&#039;&#039;&#039; folgendes: &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der Komponente eingeschaltet, wandelt sie das Graphics Objekt um zu einem passenden offscreen Graphics.&lt;br /&gt;
## ruft paintComponent() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) &lt;br /&gt;
## ruft paintBorder() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) &lt;br /&gt;
## ruft paintChildren() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) welche die Eigenschaften &amp;quot;clip&amp;quot;, &amp;quot;opaque&amp;quot; und &amp;quot;optimizedDrawingEnabled&amp;quot; verwendet, um genau festzustellen, für welche Nachkommen, &amp;quot;paint()&amp;quot; rekursiv aufzurufen ist.&lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der Komponente eingeschaltet, kopiert sie das offscreen Bild auf die Komponente unter Benutzung des ursprünglichen onscreen Graphics Objektes.&lt;br /&gt;
&lt;br /&gt;
::ANMERKUNG: die JComponent.paint() Schritte #1 und #5 werden in den rekursiven Aufrufen von paint() übersprungen (in paintChildren(), beschrieben in Schritt #4) weil alle lightweight Komponenten innerhalb einer Swingfensterhierarchie dasselbe offscreen Bild für Doppelpufferung teilen. &lt;br /&gt;
&lt;br /&gt;
(b) Der Malantrag entsteht durch einen Aufruf von repaint() auf einer Erweiterung von javax.swing.JComponent: &lt;br /&gt;
# JComponent.repaint() registriert einen asynchronen repaint Antrag beim RepaintManager der Komponente, der invokeLater() benutzt, um einen Runnable entstehen zu lassen, der den Antrag später auf dem &amp;quot;event dispatching thread&amp;quot; verarbeitet.&lt;br /&gt;
# der Runnable wird auf dem &amp;quot;event dispatching thread&amp;quot; ausgeführt und er veranlasst den RepaintManager der Komponente, &#039;&#039;&#039;paintImmediately()&#039;&#039;&#039; auf der Komponente aufzurufen, die folgendes tut: &lt;br /&gt;
## verwendet das Cliprechteck und die Eigenschaften &amp;quot;opaque&amp;quot; und &amp;quot;optimizedDrawingEnabled&amp;quot;, um die &#039;root&#039;  Komponente festzustellen, von der aus der Malvorgang anfangen muß (um sich um Transparenz und möglicherweise überlappende Komponenten kümmern zu können). &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der &#039;root&#039; Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager vom &#039;root&#039; eingeschaltet, wandelt sie das Graphics Objekt um zu einem passenden offscreen Graphics.&lt;br /&gt;
## ruft paint() auf der &#039;root&#039; Komponente auf (was die JComponent.paint() Schritte #2-4 oben unter (a) durchführt), und verursacht so, daß alles unter dem &#039;root&#039; gemalt wird, was sich mit dem Cliprechteck überschneidet.   &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der &#039;root&#039; Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der &#039;root&#039; Komponente eingeschaltet, kopiert sie das offscreen Bild auf die Komponente unter Benutzung des ursprünglichen onscreen Graphics Objektes.&lt;br /&gt;
&lt;br /&gt;
::ANMERKUNG: wenn mehrfache Aufrufe von repaint() auf einer Komponente oder irgendwelchen seiner Swingvorfahren auftreten, bevor der repaint Antrag verarbeitet wird, können jene mehrfachen Anträge in einen einzigen Callback von paintImmediately() auf der obersten Swingkomponente zusammengefasst werden, auf der repaint() aufgerufen wurde. Z.B. wenn ein JTabbedPane eine JTable enthält und beide Aufrufe von repaint() absenden, bevor irgendwelche anstehenden Anträge dieser Hierarchie verarbeitet werden, ist das Resultat ein einziger Aufruf von paintImmediately() auf dem JTabbedPane, was veranlasst, daß paint() auf beiden Komponenten durchgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Das heißt, daß update() für SwingKomponenten nie aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Obgleich repaint() einen Aufruf von paintImmediately() ergibt, gilt es nicht als &amp;quot;Malcallback&amp;quot; , und Malcode sollte nicht innerhalb einer paintImmediately() gesetzt werden. Tatsächlich gibt es im Allgemeinen überhaupt keinen Grund, paintImmediately() zu überschreiben.&lt;br /&gt;
&lt;br /&gt;
===Synchrones Zeichnen===&lt;br /&gt;
Wie im vorhergehenden Abschnitt beschrieben, dient paintImmediately() als Ausgangspunkt um einer einzelnen Swingkomponente zu sagen, sich zu malen und zu überprüfen, ob alles erforderliche Zeichnen passend geschieht. Diese Methode kann auch für synchrone Malanträge verwendet werden, wie sein Name andeutet, was manchmal bei Komponenten erfordert ist, die sicherstellen müssen, daß ihr Aussehen in Echtzeit mit ihrem internen Zustand &#039;Schritt hält&#039; (z.B. gilt dies für das JScrollPane während eines Rollvorgangs). &lt;br /&gt;
&lt;br /&gt;
Programme sollten diese Methode nicht direkt aufrufen, es sei denn, es gibt eine tatsächliche Notwendigkeit zum Zeichnen in Echtzeit. Das ist so, &#039;&#039;&#039;weil durch das asynchrone repaint() mehrfache überlappende Anträge leistungssteigernd zusammengefasst werden&#039;&#039;&#039;, während das bei Direktaufrufen von paintImmediately() nicht geschieht. Zusätzlich ist die Richtlinie für das Aufrufen dieser Methode, daß sie auf dem &amp;quot;event dispatching thread&amp;quot; aufgerufen werden muß; es ist keine API, die für den &amp;quot;multi-threading&amp;quot; Ihres Malcodes bestimmt ist! Für mehr Einzelheiten über das &amp;quot;single-threaded&amp;quot; Modell von Swing, siehe den archivierten Artikel &amp;quot;Threads and Swing&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html Threads and Swing]&lt;br /&gt;
&lt;br /&gt;
==Der RepaintManager ==&lt;br /&gt;
Der Zweck der Swingklasse &amp;quot;RepaintManager&amp;quot; ist, die Leistungsfähigkeit der repaint Verarbeitung auf einer Swing Containerhierarchie zu maximieren, und auch zur Implementierung des &amp;quot;revalidation&amp;quot; Mechanismus von Swing (letzteres wird das Thema für einen weiteren Artikel sein, siehe auch: [http://www.java-forum.org/de/viewtopic.php?p=431845#431845 Validierung mit Swing]). Sie implementiert den repaint Mechanismus, indem sie alle repaint Anträge von Swing Komponenten abfängt (also werden sie nicht mehr durch das AWT verarbeitet) und ihren eigenen Zustand beibehält in Bezug auf das, was aktualisiert werden muss (bekannt als &amp;quot;dirty regions&amp;quot;, also &amp;quot;verschmutzte Bereiche&amp;quot;). Schließlich benutzt sie invokeLater(), um die anstehenden Anträge auf dem &amp;quot;event dispatching thread&amp;quot; zu verarbeiten, wie im Abschnitt &amp;quot;Malverarbeitung&amp;quot; beschrieben (Option b). [Der RepaintManager wird eine Serie von Malanträgen möglichst zusammenfassen, wenn (und nur wenn) der &amp;quot;Anführer&amp;quot; der Serie mit invokeLater verschickt wurde, aber noch nicht auf dem EDT verarbeitet wurde.]&lt;br /&gt;
&lt;br /&gt;
Für die meisten Programme kann der RepaintManager als Teil des internen Systems von Swing angesehen werden und praktisch ignoriert werden. Jedoch liefert seine API den Programmen die Möglichkeit einer feineren Steuerung von bestimmten Aspekten des Zeichnens. &lt;br /&gt;
&lt;br /&gt;
===Der &amp;quot;gegenwärtige&amp;quot; RepaintManager ===&lt;br /&gt;
Der RepaintManager ist entworfen, um dynamisch ausgewechselt zu werden, obgleich es durch die Default-Implementierung eine einzige Instanz gibt. Die folgenden statischen Methoden lassen Programme auf den &amp;quot;gegenwärtigen&amp;quot; RepaintManager zugreifen und ihn ersetzen: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public static RepaintManager currentManager(Component c)&lt;br /&gt;
    public static RepaintManager currentManager(JComponent c)&lt;br /&gt;
    public static void setCurrentManager(RepaintManager aRepaintManager)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Den &amp;quot;gegenwärtigen&amp;quot; RepaintManager ersetzen===&lt;br /&gt;
Ein Programm würde den RepaintManager global erweitern und ersetzen, indem es folgendes tut: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    RepaintManager.setCurrentManager(new MyRepaintManager());&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Du kannst dir RepaintManagerDemo ansehen als ein einfaches lauffähiges Beispiel für die Installation von einem RepaintManager, der Informationen ausdruckt über das, was neu gezeichnet wird:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/RepaintManagerDemo.java RepaintManagerDemo]&lt;br /&gt;
&lt;br /&gt;
Ein interessanterer Grund für das Erweitern und das Ersetzen des RepaintManagers wäre die Art und Weise zu verändern, wie repaint Anträge verarbeitet werden. Zur Zeit ist der interne Zustand, der durch die Default-Implementierung benutzt wird, um schmutzige Regionen aufzuspüren, &amp;quot;package privat&amp;quot; und folglich nicht durch Unterklassen zugänglich. Jedoch können Programme ihre eigenen Mechanismen für das Aufspüren von schmutzigen Regionen und für das Zusammenfassen von repaint Anträgen einführen, indem sie die folgenden Methoden überschreiben: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public synchronized void addDirtyRegion(JComponent c, int x, int y, int w, int h) &lt;br /&gt;
    public Rectangle getDirtyRegion(JComponent aComponent)&lt;br /&gt;
    public void markCompletelyDirty(JComponent aComponent) &lt;br /&gt;
    public void markCompletelyClean(JComponent aComponent) {&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die addDirtyRegion() Methode ist die, die aufgerufen wird, wenn repaint() auf einer Swingkomponente aufgerufen wird, und kann folglich angespannt werden, um alle repaint Anträge abzufangen. Wenn ein Programm diese Methode überschreibt (und nicht super.addDirtyRegion() aufruft), dann wird es dafür verantwortlich, invokeLater() zu benutzen, um einen Runnable auf die &amp;quot;EventQueue&amp;quot; zu setzen, der paintImmediately() auf einer passenden Komponente aufruft (Übersetzung: nicht für Leute mit schwachem Herzen).&lt;br /&gt;
&lt;br /&gt;
===Globale Steuerung der Doppelpufferung===&lt;br /&gt;
Der RepaintManager stellt eine API zur Verfügung, um die Doppelpufferung global zu ermöglichenden und zu sperren: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void setDoubleBufferingEnabled(boolean aFlag)&lt;br /&gt;
    public boolean isDoubleBufferingEnabled()&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Während der Verarbeitung eines Malvorgangs wird diese Eigenschaft innerhalb JComponent überprüft, um festzustellen, ob man einen offscreen Puffer für die Darstellung verwendet. Diese Eigenschaft hat den Default-Wert &amp;quot;true&amp;quot;, aber die Programme, die Doppelpufferung für alle Swingkomponenten global sperren möchten, können folgendes tun: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    RepaintManager.currentManager(mycomponent).setDoubleBufferingEnabled(false);&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkung: da die Default-Implementierung von Swing einen einzigen RepaintManager instanziert, ist das &amp;quot;mycomponent&amp;quot; Argument irrelevant.&lt;br /&gt;
&lt;br /&gt;
==Swing Malrichtlinien ==&lt;br /&gt;
Swingprogramme sollten diese Richtlinien verstehen, wenn Malcode geschrieben wird: &lt;br /&gt;
&lt;br /&gt;
# Für Swingkomponenten wird immer &#039;&#039;paint()&#039;&#039; aufgerufen als Ergebnis sowohl von systemausgelösten als auch von anwendungsausgelösten Malanträgen; &#039;&#039;update()&#039;&#039; wird nie auf Swingkomponenten aufgerufen. &lt;br /&gt;
# Programme können einen zukünftigen Aufruf von &#039;&#039;paint()&#039;&#039; auslösen, indem sie &#039;&#039;repaint()&#039;&#039; aufrufen, aber sie sollten &#039;&#039;paint()&#039;&#039; nicht direkt aufrufen. &lt;br /&gt;
# Auf Komponenten mit komplizierter Ausgabe, sollte &#039;&#039;repaint()&#039;&#039; mit Argumenten aufgerufen werden, die nur das Rechteck, das aktualisieren muß, definieren, und nicht die keine-Argumente-Version, die die gesamte Komponente veranlasst, neu gezeichnet zu werden. &lt;br /&gt;
# Die Swing Implementierung von paint() unterteilt den Aufruf in 3 verschiedene callback Methoden:&lt;br /&gt;
#* &#039;&#039;paintComponent()&#039;&#039;:  Erweiterungen von Swingkomponenten, die ihren eigenen Malcode einführen möchten, sollten diesen Code innerhalb des Bereichs der Methode paintComponent() setzen (nicht innerhalb von paint()). &lt;br /&gt;
#* &#039;&#039;paintBorder()&#039;&#039; &lt;br /&gt;
#* &#039;&#039;paintChildren()&#039;&#039; &lt;br /&gt;
# Swing stellt zwei Eigenschaften vor, um die Malleistung zu maximieren: &lt;br /&gt;
#*&#039;&#039;opaque&#039;&#039;: malt die Komponente alle ihre Bits oder nicht? &lt;br /&gt;
#*&#039;&#039;optimizedDrawingEnabled&#039;&#039;: können irgendwelche der Kinder dieser Komponente sich überschneiden? &lt;br /&gt;
# Wenn die &#039;&#039;opaque&#039;&#039; Eigenschaft einer Swingkomponente auf &#039;&#039;true&#039;&#039; gesetzt wird, dann erklärt sie sich damit einverstanden, alle Bits zu malen, die innerhalb ihrer Grenzen enthalten sind (dies schließt das Löschen ihres eigenen Hintergrundes innerhalb von &#039;&#039;paintComponent()&#039;&#039; ein), andernfalls können Bilschirmunreinheiten auftreten.&lt;br /&gt;
# Das Setzen entweder von &#039;&#039;opaque&#039;&#039; oder &#039;&#039;optimizedDrawingEnabled&#039;&#039; auf &#039;&#039;false&#039;&#039; für eine Komponente verursacht mehr Verarbeitung bei jedem Malvorgang, folglich empfehlen wir vernünftigen Gebrauch von Transparenz und überlappenden Komponenten zu machen. &lt;br /&gt;
# Erweiterungen von Swingkomponenten, die &#039;&#039;UI Delegates&#039;&#039; haben (einschließlich &#039;&#039;JPanel&#039;&#039;), sollten gewöhnlich &#039;&#039;super.paintComponent()&#039;&#039; innerhalb ihrer eigenen &#039;&#039;paintComponent()&#039;&#039; Implementierung aufrufen. Da der &#039;&#039;UI Delegate&#039;&#039; die Verantwortung für das Löschen des Hintergrundes auf undurchlässigen Komponenten hat, kümmert er sich um #6.&lt;br /&gt;
# Swing unterstützt eingebaute Doppelpufferung über die &#039;&#039;doubleBuffered&#039;&#039; Eigenschaft von &#039;&#039;JComponent&#039;&#039;, und ihr Default-Wert ist &#039;&#039;true&#039;&#039; für alle Swingkomponenten, gleichwohl das Setzen auf &#039;&#039;true&#039;&#039; auf einem Swingcontainer den allgemeinen Effekt hat, sie für alle lightweight Nachkommen dieses Containers einzuschalten, unabhängig von ihren einzelnen Einstellungen.&lt;br /&gt;
# Es wird ausdrücklich empfohlen, daß Doppelpufferung für alle Swingkomponenten ermöglicht wird.  &lt;br /&gt;
# Komponenten, die komplizierte Ausgaben darstellen, sollten intelligenten Gebrauch vom Cliprechteck machen, um die Malvorgänge auf diejenigen zu beschränken, die sich mit dem Clipbereich schneiden.&lt;br /&gt;
&lt;br /&gt;
=Zusammenfassung =&lt;br /&gt;
Beide, AWT und Swing, liefern APIs, um es den Programmen einfach zu machen, ihren Inhalt korrekt am Bildschirm darzustellen. Obgleich wir empfehlen, daß Entwickler für die meisten GUI Bedürfnisse Gebrauch von Swing machen, ist es nützlich, AWTs Malmechanismus zu verstehen, weil derjenige von Swing darauf aufbaut.&lt;br /&gt;
&lt;br /&gt;
Um die beste Leistung von diesen APIs zu erhalten, müssen Anwendungsprogramme die Verantwortung dafür übernehmen, die in diesem Dokument umrissenen Richtlinien zu befolgen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;br /&gt;
[[Kategorie:Swing]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Malen_in_AWT_und_Swing&amp;diff=5201</id>
		<title>Malen in AWT und Swing</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Malen_in_AWT_und_Swing&amp;diff=5201"/>
		<updated>2013-01-12T06:31:16Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Malen in AWT und Swing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
=Malen in AWT und Swing=&lt;br /&gt;
Guter Malcode ist der Schlüssel zu einer leistungsfähigen Anwendung.&lt;br /&gt;
&lt;br /&gt;
Von Amy Fowler.&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/ Copyright 1994-2008 Sun Microsystems, Inc.] &lt;br /&gt;
&lt;br /&gt;
Übersetzung: André Uhres (Ich habe bei Sun die Erlaubnis angefragt, diesen Artikel zu übersetzen und hier zu veröffentlichen)&lt;br /&gt;
&lt;br /&gt;
*HINWEIS vom Übersetzer: Zum Einstieg in das Malen mit Swing ist auch der folgende kurze und praxisorientierte Artikel gut geeignet: [[Malen in Swing Teil 1: der grundlegende Mechanismus]]&lt;br /&gt;
&lt;br /&gt;
In einem graphischen System ist normalerweise ein Fensterdarstellungstoolkit dafür verantwortlich, einen Rahmen zur Verfügung zu stellen, der es relativ einfach macht, auf einer graphischen Benutzerschnittstelle (GUI) die richtigen Bits zur richtigen Zeit darzustellen.&lt;br /&gt;
Sowohl [[AWT]] (abstraktes Fensterdarstellungstoolkit) als auch [[Swing]] liefern solch einen Rahmen. &lt;br /&gt;
Aber die [[API]]s, die ihn verwirklichen, werden von manchen [[Entwickler]]n nicht gut verstanden -- ein Problem, das zu Programmen geführt hat, die nicht so leistungsfähig sind, wie sie sein könnten. &lt;br /&gt;
&lt;br /&gt;
Dieser Artikel beschreibt die AWT und Swing Malmechanismen im Einzelnen. Sein Zweck ist, Entwicklern zu helfen, korrekten und leistungsfähigen GUI Malcode zu schreiben. Während der Artikel die allgemeinen Malmechanismen umfaßt (wo und wann man darstellt), erklärt er nicht, wie man die Swing Graphiken APIs benutzt, um korrekte Graphiken darzustellen. Um zu erlernen wie man nette Graphiken macht, besichtigen Sie bitte die [http://docs.oracle.com/javase/tutorial/2d/index.html Java 2D Website].&lt;br /&gt;
&lt;br /&gt;
=Entwicklung des Swing Malsystems=&lt;br /&gt;
&lt;br /&gt;
Als die ursprüngliche AWT API für [[JDK]] 1.0 entwickelt wurde, gab es nur heavyweight Komponenten (&amp;quot;heavyweight&amp;quot; bedeutet, daß die Komponente ihr eigenes undurchlässiges natives Fenster hat). Dies erlaubte es dem AWT, sich voll auf das Maluntersystem der nativen Plattform zu stützen. Dieser Entwurf kümmerte sich um Einzelheiten wie Beschädigungserkennung, Clipberechnung und Z-Einrichtung. &lt;br /&gt;
&lt;br /&gt;
Mit der Einführung der lightweight Komponenten in JDK 1.1 (eine &amp;quot;lightweight&amp;quot; Komponente ist eine, die das native Fenster ihres nächsten heavyweight Vorfahrs wiederverwendet), mußte das AWT das Malen für lightweight Komponenten im gemeinsamen Java Code einführen. Somit gibt es feine Unterschiede bezüglich des Malvorgangs für heavyweight und lightweight Komponenten. Nach dem JDK 1.1, als das Swing Toolkit freigegeben wurde, stellte dieses seine eigenen Malmechanismen vor. In den meisten Fällen ähnelt und beruht der Swing Malmechanismus auf dem AWT. Aber er führt auch einige Unterschiede bezüglich der Mechanismen ein, sowie neue APIs, mit denen die Anwendungen den Malvorgang einfacher anpassen können.&lt;br /&gt;
&lt;br /&gt;
=Malen in AWT=&lt;br /&gt;
&lt;br /&gt;
Zu verstehen, wie die Mal-API von AWT arbeitet, hilft zu erkennen, was einen Malvorgang in einer Fensterdarstellungsumgebung auslöst. In AWT gibt es zwei Arten von Malvorgängen: systemausgelöstes Malen und anwendungsausgelöstes Malen. &lt;br /&gt;
&lt;br /&gt;
==Systemausgelöstes Malen==&lt;br /&gt;
&lt;br /&gt;
In einem systemausgelösten Malvorgang, bittet das System eine Komponente, ihren Inhalt darzustellen, normalerweise aus einem der folgenden Gründe: &lt;br /&gt;
&lt;br /&gt;
* Die Komponente wird zum erstenmal sichtbar auf dem [[Bildschirm]] abgebildet. &lt;br /&gt;
* Die Komponente wird in der Größe verändert.&lt;br /&gt;
* Die Komponente wurde beschädigt und muß repariert werden (zum Beispiel wurde etwas verschoben, das vorher die Komponente verdeckte, und ein vorher verdeckter Teil der Komponente wird sichtbar).&lt;br /&gt;
&lt;br /&gt;
==Anwendungsausgelöstes Malen==&lt;br /&gt;
&lt;br /&gt;
Bei einem anwendungsausgelösten Malvorgang entscheidet die Komponente, daß sie ihren Inhalt aktualisieren muß, weil sich ihr interner [[Zustand]] geändert hat. Beispiel: ein Button erkennt, daß eine [[Maus]]taste betätigt worden ist und stellt fest, daß er einen &amp;quot;niedergedrückten&amp;quot; Button malen muß.&lt;br /&gt;
&lt;br /&gt;
==Die paint Methode==&lt;br /&gt;
&lt;br /&gt;
Ungeachtet dessen, wie ein Malantrag ausgelöst wird, benutzt das AWT einen &amp;quot;callback&amp;quot; (&amp;quot;Wiederholungsbesuch&amp;quot;) Mechanismus zum Zeichnen, und dieser Mechanismus ist derselbe für heavyweight und lightweight Komponenten. Das heißt, daß ein [[Programm]] den Darstellungscode der [[Komponente]] innerhalb einer bestimmten überschriebenen [[Methode]] setzen sollte, und das [[Toolkit]] ruft diese Methode auf, wenn es Zeit ist zu malen. Die zu überschreibende Methode ist in &#039;&#039;&#039;java.awt.Component&#039;&#039;&#039;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;public void paint(Graphics g)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn AWT diese Methode aufruft, ist der Parameter &amp;quot;Graphics g&amp;quot; mit dem passenden Zustand für das Zeichnen auf dieser bestimmten Komponente vorkonfiguriert: &lt;br /&gt;
&lt;br /&gt;
* Die Farbe des Graphics Objektes wird auf die foreground-Eigenschaft der Komponente eingestellt. &lt;br /&gt;
* Die Schriftart des Graphics Objektes wird auf die font-Eigenschaft der Komponente eingestellt. &lt;br /&gt;
* Die &amp;quot;translation&amp;quot; des Graphics Objektes wird so eingestellt, daß die Koordinate (0,0) die obere linke Ecke der Komponente darstellt. &lt;br /&gt;
* Das &amp;quot;clip&amp;quot;-Rechteck des Graphics Objektes wird auf den Bereich der Komponente eingestellt, der neu gezeichnet werden muss. &lt;br /&gt;
&lt;br /&gt;
Programme müssen dieses Graphics Object verwenden (oder ein von ihm abgeleitetes) um die Oberfläche darzustellen. Sie sind frei, den Zustand des Graphics Objektes so zu ändern, wie es benötigt wird.&lt;br /&gt;
Hier ist ein einfaches Beispiel von einem paint callback, der einen gefüllten Kreis innerhalb einer Komponente darstellt: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void paint(Graphics g) {&lt;br /&gt;
        // Dynamically calculate size information&lt;br /&gt;
        Dimension size = getSize();&lt;br /&gt;
        // diameter&lt;br /&gt;
        int d = Math.min(size.width, size.height); &lt;br /&gt;
        int x = (size.width - d)/2;&lt;br /&gt;
        int y = (size.height - d)/2;&lt;br /&gt;
&lt;br /&gt;
        // draw circle (color already set to foreground)&lt;br /&gt;
        g.fillOval(x, y, d, d);&lt;br /&gt;
        g.setColor(Color.black);&lt;br /&gt;
        g.drawOval(x, y, d, d);&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Entwickler, die neu bei AWT sind, werden einen Blick auf das PaintDemo Beispiel werfen wollen, das ein lauffähiges Programmbeispiel liefert, wie man den paint callback in einem AWT Programm verwendet:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/PaintDemo.java PaintDemo]&lt;br /&gt;
&lt;br /&gt;
Im allgemeinen sollten Programme es vermeiden, darstellenden Code an irgendeinen Punkt zu setzen, wo er von außerhalb des Bereichs der paint callback Methode aufgerufen werden könnte. Warum? Weil solcher Code manchmal aufgerufen werden kann, wenn es nicht angebracht ist zu malen -- zum Beispiel bevor die Komponente sichtbar ist oder Zugang zu einem gültigen Graphics Objekt hat. Es wird nicht empfohlen, daß Programme paint() direkt aufrufen. &lt;br /&gt;
&lt;br /&gt;
Um anwendungsausgelöstes Malen zu ermöglichen, liefert das AWT die folgenden &#039;&#039;&#039;java.awt.Component&#039;&#039;&#039; Methoden, damit Programme einen asynchronen Malvorgang anfragen können: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void repaint() &lt;br /&gt;
    public void repaint(long tm) &lt;br /&gt;
    public void repaint(int x, int y, int width, int height) &lt;br /&gt;
    public void repaint(long tm, int x, int y, int width, int height)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der folgende Code zeigt ein einfaches Beispiel von einem MouseListener, der repaint() benutzt, um Updates auf einer theoretischen Taste auszulösen, wenn die Maus gedrückt und losgelassen wird: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;        MouseListener l = new MouseAdapter() {&lt;br /&gt;
            public void mousePressed(MouseEvent e) {&lt;br /&gt;
                MyButton b = (MyButton)e.getSource();&lt;br /&gt;
                b.setSelected(true);&lt;br /&gt;
                b.repaint();            &lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            public void mouseReleased(MouseEvent e) {&lt;br /&gt;
                MyButton b = (MyButton)e.getSource();&lt;br /&gt;
                b.setSelected(false);&lt;br /&gt;
                b.repaint();            &lt;br /&gt;
            }&lt;br /&gt;
        };&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Komponenten, die komplizierte Darstellungen ausgeben, sollten repaint() mit den Argumenten aufrufen, welche nur den Bereich definieren, der eine Aktualisierung erfordert. Es ist ein allgemeiner Fehler, immer die keine-Argumente Version zu benutzen, die immer die gesamte Komponente neu zeichnet, was häufig zu nicht notwendigen Malverarbeitungen führt. &lt;br /&gt;
&lt;br /&gt;
===paint() gegen update()===&lt;br /&gt;
Warum unterscheiden wir zwischen systemausgelöstem und anwendungsausgelöstem Malen? Weil AWT jeden dieser Fälle etwas anders für heavyweight Komponenten behandelt (der lightweight Fall wird später besprochen), was leider eine Quelle großer Verwirrung ist. &lt;br /&gt;
&lt;br /&gt;
Für heavyweight Komponenten geschehen diese zwei Arten des Zeichnens in zwei unterschiedlichen Wegen, abhängig davon, ob ein Malvorgang systemausgelöst oder anwendungsausgelöst ist.&lt;br /&gt;
&lt;br /&gt;
====systemausgelöstes Malen====&lt;br /&gt;
dies ist, wie ein systemausgelöster Malvorgang stattfindet: &lt;br /&gt;
&lt;br /&gt;
# Das AWT stellt fest, daß entweder ein Teil oder die ganze Komponente gemalt werden muß. &lt;br /&gt;
# Das AWT veranlasst den Event Dispatch Thread, paint() auf der Komponente aufzurufen.&lt;br /&gt;
&lt;br /&gt;
====anwendungsausgelöstes Malen====&lt;br /&gt;
Ein anwendungsausgelöster Malvorgang findet wie folgt statt: &lt;br /&gt;
&lt;br /&gt;
# Das Programm stellt fest, daß entweder ein Teil oder die ganze Komponente in Erwiderung auf eine interne Zustandsänderung neu gezeichnet werden muß. &lt;br /&gt;
# Das Programm ruft repaint() auf der Komponente auf, was einen asynchronen Antrag zum AWT registriert, daß diese Komponente neu gezeichnet werden muß. &lt;br /&gt;
# Das AWT veranlasst den Event Dispatch Thread, ein update() auf der Komponente aufzurufen. ANMERKUNG: Erfolgen mehrfache repaint() Aufrufe auf einer Komponente bevor der erste Antrag verarbeitet wird, können die mehrfachen Anträge zu einem einzigen Aufruf von update() zusammengefasst werden. Der Algorithmus für die Bestimmung, wann mehrfache Anträge zusammengefasst werden sollten, ist Implementierungsabhängig. Wenn mehrfache Anträge zusammengefasst werden, ist das resultierende Updaterechteck gleich der Vereinigung der Rechtecke, die in den zusammengefassten Anträgen enthalten sind. &lt;br /&gt;
# Wenn die Komponente nicht update() überschreibt, löscht die Default-Implementierung von update() den Hintergrund der Komponente (wenn es nicht eine lightweight Komponente ist) und ruft einfach paint() auf. &lt;br /&gt;
&lt;br /&gt;
Da bei der Default-Implementierung das abschließende Resultat dasselbe ist wie bei paint(), verstehen viele Leute den Zweck einer unterschiedlichen update() Methode nicht. Während es zutreffend ist, daß die Default-Implementierung von update() die paint() aufruft, ermöglicht dieser &amp;quot;Updatehaken&amp;quot; einem Programm, den anwendungsausgelösten Malvorgang anders anzufassen, wenn es gewünscht wird. Ein Programm muß annehmen, daß ein Aufruf von paint() andeutet, daß der Bereich, der durch das Cliprechteck vom Graphics definiert wird, &amp;quot;beschädigt&amp;quot; ist und vollständig neu gezeichnet werden muß, gleichwohl ein Aufruf von update() dieses nicht andeutet, was einem Programm ermöglicht, zusätzliches Zeichnen zu tun. &lt;br /&gt;
&lt;br /&gt;
Zusätzliches Zeichnen (&amp;quot;incremental painting&amp;quot;) ist nützlich, wenn ein Programm die zusätzliche Darstellung über die vorhandenen Teilstücke dieser Komponente überlagern möchte. Das UpdateDemo Beispiel zeigt ein Programm, das Nutzen aus dem Verwenden von update() zieht, um zusätzliches Zeichnen zu tun:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/UpdateDemo.java UpdateDemo]&lt;br /&gt;
&lt;br /&gt;
In Wahrheit braucht die Mehrheit der GUI Komponenten kein zusätzliches Zeichnen zu tun. So können die meisten Programme die update() Methode ignorieren und einfach paint() überschreiben, um die Komponente in ihrem gegenwärtigen Zustand darzustellen. Das heißt, daß die systemausgelöste und anwendungsausgelöste Darstellung im Wesentlichen für die meisten Implementierungen gleichbedeutend ist.&lt;br /&gt;
&lt;br /&gt;
==Das Malen und die lightweight Komponenten ==&lt;br /&gt;
Von der Perspektive des Anwendungsentwicklers, ist die Mal-API im Allgemeinen dieselbe für lightweight und heavyweight Komponenten (das heißt, er überschreibt paint() und ruft repaint() auf, um Updates auszulösen). Jedoch seit AWTs lightweight Komponentenrahmen völlig im allgemeinen [[Java]] Code geschrieben wurde, sind dort einige subtile Unterschiede bezüglich der Weise, wie der Mechanismus für lightweight Komponenten implementiert wird. &lt;br /&gt;
&lt;br /&gt;
===Wie lightweight Komponenten gemalt werden===&lt;br /&gt;
Damit eine lightweight Komponente besteht, benötigt sie einen heavyweight Vorfahr in der Containerhierarchie, um einen Platz zum Malen zu haben. Wenn diesem heavyweight Vorfahr gesagt wird, sein Fenster zu malen, muß er den Malaufruf übersetzen in Malaufrufe an alle seine lightweight Nachkommen. Dies wird durch die paint() Methode von &#039;&#039;&#039;java.awt.Container&#039;&#039;&#039; verarbeitet, welche paint() auf irgendwelchen seiner sichtbaren lightweight Kinder aufruft, die sich mit dem zu malenden Rechteck überschneiden. So ist es für alle Containerunterklassen (lighweight oder heavyweight), welche paint() überschreiben, notwendig, folgendes zu tun: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public class MyContainer extends Container {&lt;br /&gt;
        public void paint(Graphics g) {&lt;br /&gt;
	    // paint my contents first...&lt;br /&gt;
	    // then, make sure lightweight children paint&lt;br /&gt;
	    super.paint(g); &lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn der Aufruf von super.paint() fehlt, dann werden die lightweight Nachkommen des Containers nicht dargestellt (ein sehr verbreitetes Problem als JDK 1.1 die lightweight Komponenten einführte). &lt;br /&gt;
&lt;br /&gt;
Es ist nützlich anzumerken, daß die Default-Implementierung von Container.update() nicht die Rekursion verwendet, um update() oder paint() auf lightweight Nachkommen aufzurufen. Das heißt, daß irgendeine heavyweight Containerunterklasse, die update() benutzt, um zusätzlichen Zeichnen zu tun, sichergehen muß, daß lightweight Nachkommen wenn nötig rekursiv neu gezeichnet werden. Glücklicherweise benötigen wenige heavyweight Container zusätzliches Zeichnen, also beeinflußt diese Frage die meisten Programme nicht.&lt;br /&gt;
&lt;br /&gt;
===lightweight und systemausgelöstes Malen ===&lt;br /&gt;
Der lightweight Rahmencode, der das Fensterdarstellungsverhalten für lightweight Komponenten einführt (sichtbar machen, verstecken, bewegen, die Größe neu bestimmen, usw..), ist völlig in Java geschrieben. Innerhalb der Java Implementierung dieser Funktionen, muß das AWT häufig verschiedenen lightweight Komponenten ausdrücklich erklären, sich  zu malen (im Wesentlichen systemausgelöstes Malen, obwohl es nicht mehr vom nativen System ausgeht). Jedoch benutzt der lightweight Rahmen &#039;&#039;&#039;repaint()&#039;&#039;&#039;, um Komponenten zu erklären, sich zu malen, was einen Aufruf von update() anstatt eines Direktaufrufs von paint() ergibt, wie wir oben gesehen haben. Folglich kann systemausgelöstes Zeichnen für lightweight Komponenten zwei Wegen folgen: &lt;br /&gt;
&lt;br /&gt;
* Der systemausgelöste Malantrag entsteht im nativen System (d.h. der heavyweight Vorfahr der lightweight Komponente wird zum ersten Mal sichtbar), was einen Direktaufruf von paint() ergibt. &lt;br /&gt;
* Der systemausgelöste Malantrag entsteht im lightweight Rahmen (d.h., die Größe der lightweight Komponente wird neu bestimmt), was einen Aufruf von update() ergibt, der in der Default-Implementierung an paint() weitergeleitet wird. &lt;br /&gt;
&lt;br /&gt;
Dies bedeutet, daß es für lightweight Komponenten &#039;&#039;&#039;keine reale Unterscheidung zwischen update() und paint() gibt&#039;&#039;&#039;, was weiter bedeutet, daß die zusätzliche Zeichnentechnik (incremental painting) nicht für lightweight Komponenten verwendet werden sollte.&lt;br /&gt;
&lt;br /&gt;
===lightweight und Transparenz===&lt;br /&gt;
Da lightweight Komponenten den Bildschirmplatz eines heavyweight Vorfahrs &amp;quot;borgen&amp;quot;, unterstützen sie die Eigenschaft der Transparenz. Dies funktioniert, weil lightweight Komponenten von hinten nach vorne gemalt werden und folglich, wenn eine lightweight Komponente einige oder all ihre Bits unbemalt läßt, die dahinterliegende Komponente &amp;quot;durchscheint&amp;quot;.  Dies ist auch der Grund, warum die Default-Implementierung von update() den Hintergrund nicht löscht, wenn die Komponente lightweight ist. &lt;br /&gt;
&lt;br /&gt;
Das LightweightDemo Programmbeispiel zeigt die Transparenzeigenschaft der lightweight Komponenten:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/LightweightDemo.java LightweightDemo]&lt;br /&gt;
&lt;br /&gt;
==Das &amp;quot;intelligente&amp;quot; Malen==&lt;br /&gt;
Während das AWT versucht, den Prozeß der Darstellung der Komponenten so leistungsfähig wie möglich zu machen, kann die paint() Implementierung einer Komponente selbst eine bedeutende Auswirkung auf die gesamte Leistung haben. Zwei Schlüsselbereiche, die diesen Prozeß beeinflussen können, sind: &lt;br /&gt;
&lt;br /&gt;
* Die Clipinformationen verwenden, um den Bereich, der dargestellt wird, einzuschränken.&lt;br /&gt;
* Internes Wissen über das Layout verwenden, um den Bereich, welche Kinder gemalt werden, einzuschränken (nur lightweight). &lt;br /&gt;
&lt;br /&gt;
Wenn deine Komponente einfach ist -- zum Beispiel, wenn es eine Drucktaste ist -- dann ist sie die Mühe nicht wert, die Darstellung zu bearbeiten, um nur den Teil zu malen, der das Cliprechteck überschneidet; es ist vorzuziehend, die gesamte Komponente zu malen und die Graphics passend einschränken zu lassen. Wenn du jedoch eine Komponente mit komplizierter Ausgabe erzeugt hast, wie eine Textkomponente, dann ist es notwendig, daß dein Code die Clipinformationen gebraucht, um den Umfang der Darstellung einzuschränken.&lt;br /&gt;
&lt;br /&gt;
Weiter, wenn du einen komplizierten lightweight Container schreibst, der zahlreiche Komponenten beherbergt, wo der Container und/oder sein Layoutmanager Informationen über das Layout hat, dann ist er es wert dieses Layoutwissen zu verwenden, um intelligenter in der Bestimmung zu sein, welche der Kinder gemalt werden müssen. Die Default-Implementierung von Container.paint() schaut einfach der Reihe nach durch die Kinder und prüft die Sichtbarkeit und Überschneidung -- ein Vorgang, der mit bestimmten Layouts unnötigerweise aufwendig sein kann. Zum Beispiel, wenn ein Container die Komponenten in einem Rasterfeld 100x100 auslegt, dann könnte diese Rasterfeldinformation verwendet werden, schneller festzustellen, welche von jenen 10000 Komponenten das Cliptechteck überschneiden und wirklich gemalt werden müssen.&lt;br /&gt;
&lt;br /&gt;
==AWT Malrichtlinien ==&lt;br /&gt;
Das AWT stellt eine einfache callback API für das Malen von Komponenten zur Verfügung. Wenn du sie verwendest, treffen die folgenden Richtlinien zu: &lt;br /&gt;
&lt;br /&gt;
# Für die meisten Programme sollte aller Malcode innerhalb des Bereichs der paint() Methode der Komponente gesetzt werden. &lt;br /&gt;
# Programme können einen zukünftigen Aufruf von paint() auslösen, indem sie repaint() aufrufen, aber sie sollten nicht paint() direkt aufrufen. &lt;br /&gt;
# Bei Komponenten mit komplizierter Ausgabe, sollte repaint() mit Argumenten aufgerufen werden, die nur das Rechteck definieren, das aktualisieren muß, anstatt der keine-Argumente Version, die die gesamte Komponente veranlasst neu gezeichnet zu werden. &lt;br /&gt;
# Da ein Aufruf von repaint() zuerst einen Aufruf von update() ergibt, der in der Default-Implementierung an paint() weitergeleitet wird, können heavyweight Komponenten update() überschreiben, um zusätzliches Zeichnen (incremental painting) zu tun, wenn es gewünscht wird (lightweight Komponenten unterstützen nicht das zusätzliche Zeichnen).&lt;br /&gt;
# Erweiterungen von java.awt.Container, die paint() überschreiben, sollten immer super.paint() aufrufen, um sicherzustellen, dass die Kinder gemalt werden. &lt;br /&gt;
# Komponenten mit komplizierter Ausgabe sollten intelligenten Gebrauch vom Cliprechteck machen, um den Malvorgang auf den Bereich zu beschränken, der sich mit dem Clipbereich überschneidet.&lt;br /&gt;
&lt;br /&gt;
=Malen in Swing=&lt;br /&gt;
Swing beginnt mit AWTs grundlegendem Malmodell und erweitert es, um die Leistung zu maximieren und die Erweiterbarkeit zu verbessern. Wie AWT, so unterstützt auch Swing den Malcallback und den Gebrauch von repaint(), um Updates auszulösen. Zusätzlich gibt Swing eingebaute Unterstützung für Doppelpufferung sowie Änderungen, um die zusätzliche Swing Struktur zu unterstützen (wie Ränder und der UI Delegate). Und schließlich stellt Swing die RepaintManager API für jene Programme zur Verfügung, die den Malmechanismus weiter anpassen möchten.&lt;br /&gt;
&lt;br /&gt;
==Unterstützung für Doppelpufferung ==&lt;br /&gt;
Eine der bemerkenswertesten Eigenschaften von Swing ist, daß es die Unterstützung für Doppelpufferung direkt ins Toolkit einbaut. Das geschieht durch die Bereitstellung der &amp;quot;doubleBuffered&amp;quot; Eigenschaft in &#039;&#039;&#039;javax.swing.JComponent: &lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isDoubleBuffered()&lt;br /&gt;
    public void setDoubleBuffered(boolean o)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Doppelpufferung von Swing benutzt einen einzigen offscreen Puffer pro Containerhierarchie (normalerweise einen pro Fenster) wo die Doppelpufferung eingeschaltet worden ist. Obgleich diese Eigenschaft pro Komponente eingeschaltet werden kann, ergibt ihre Einschaltung in einem bestimmten Container den Effekt, dass alle lightweight Komponenten darunter in dem offscreen Puffer dargestellt werden, unabhängig davon wie die individuelle &amp;quot;doubleBuffered&amp;quot; Eigenschaft eingestellt ist.&lt;br /&gt;
&lt;br /&gt;
Der Default-Wert dieser Eigenschaft ist bei allen Swingkomponenten auf &amp;quot;true&amp;quot; gesetzt. Aber die Einstellung, die wirklich zählt, ist in JRootPane, weil diese Einstellung effektiv Doppelpufferung für alles darunter einschaltet. In den meisten Fällen brauchen Swingprogramme nichts zu tun in Bezug auf Doppelpufferung, ausgenommen, zu entscheiden, ob sie ein- oder ausgeschaltet sein sollte (und für eine flackerfreie GUI wirst du wünschen, dass sie eingeschaltet ist!). Swing stellt sicher, daß die passende Art des Graphics Objektes (offscreen Bild Graphics für Doppelpufferung, sonst die original Graphics) der  Komponente übergeben wird, so braucht die Komponente lediglich mit ihm zu zeichnen. Dieser Mechanismus wird später in diesem Artikel ausführlicher erklärt (im Abschnitt über die Malverarbeitung).&lt;br /&gt;
&lt;br /&gt;
==Zusätzliche Maleigenschaften ==&lt;br /&gt;
Swing stellt einige zusätzliche Eigenschaften von JComponent vor, um die Leistungsfähigkeit der internen Malalgorithmen zu verbessern. Diese Eigenschaften wurden eingeführt, um sich mit den folgenden zwei Fragen zu beschäftigen, die das Zeichnen von lightweight Komponenten zu einem kostspieligen Vorgang machen können: &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Transparenz&#039;&#039;&#039;: Wenn eine lightweight Komponente gemalt wird, ist es möglich, daß die Komponente nicht alle ihre Bits malt, wenn sie teilweise oder ganz transparent ist; das heißt, daß, wann immer sie neu gezeichnet wird, das was dahinter liegt zuerst neu gezeichnet werden muss. Das erfordert vom System, die Containerhierarchie hinaufzugehen um den ersten zugrundeliegenden heavyweight Vorfahr zu finden, von dem der hinten-nach-vorne Malvorgang ausgehen soll. &lt;br /&gt;
* &#039;&#039;&#039;Überlappende Komponenten&#039;&#039;&#039;: Wenn eine lightweight Komponente gemalt wird, ist es möglich, daß irgendeine andere lightweight Komponente sie teilweise verdeckt; das heißt, daß, wann immer die ursprüngliche lightweight Komponente gemalt wird, alle möglichen Komponenten, die die ursprüngliche Komponente überdecken (wo das Cliprechteck sich mit dem überlappenden Bereich schneidet), auch teilweise neu gezeichnet werden müssen. Dies erfordert vom System, bei jedem Malvorgang viel von der Containerhierarchie zu durchqueren und auf überlappende Komponenten zu überprüfen. &lt;br /&gt;
&lt;br /&gt;
===Die Opazität===&lt;br /&gt;
Um im Fall von undurchlässigen Komponenten die Leistung zu verbessern, fügt Swing eine &amp;quot;opaque&amp;quot; Lese-Schreibeigenschaft zu javax.swing.JComponent hinzu: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isOpaque()&lt;br /&gt;
    public void setOpaque(boolean o)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Einstellungen sind: &lt;br /&gt;
&lt;br /&gt;
*true: Die Komponente ist damit einverstanden, alle ihre Bits zu malen, die innerhalb ihrer rechteckigen Grenzen enthalten sind.&lt;br /&gt;
*false: Der Komponente gibt keine Garantien über das Malen aller Bits innerhalb ihrer rechteckigen Grenzen. &lt;br /&gt;
&lt;br /&gt;
Die &amp;quot;opaque&amp;quot; Eigenschaft läßt das Malsystem von Swing ermitteln, ob ein repaint Antrag auf einer bestimmten Komponente zusätzliche repaint Anträge der dahinter liegenden Vorfahren erfordert oder nicht. Der Default-Wert der &amp;quot;opaque&amp;quot; Eigenschaft für jede standard Swingkomponente wird durch das gegenwärtige Look and Feel UI Objekt eingestellt. Der Wert ist für die meisten Komponenten &amp;quot;true&amp;quot;. &lt;br /&gt;
&lt;br /&gt;
Einer der allgemeinsten Fehler, die Komponentenimplementierungen machen, ist, daß sie die &amp;quot;opaque&amp;quot; Eigenschaft auf &amp;quot;true&amp;quot; belassen, und dennoch den Bereich nicht vollständig darstellen, der durch ihre Grenzen definiert ist, was gelegentliche Unreinheiten in den nicht dargestellten Bereichen ergibt. Wenn eine Komponente entworfen wird, sollte sorgfältig überlegt werden, wie die &amp;quot;opaque&amp;quot; Eigenschaft zu behandeln ist, sowohl um sicherzustellen, daß Transparenz klug benutzt wird, da sie mehr Darstellungszeit kostet, und daß die Übereinkunft mit dem Malsystem eingehalten wird. &lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der &amp;quot;opaque&amp;quot; Eigenschaft wird häufig mißverstanden. Manchmal wird sie verstanden als &amp;quot;den Hintergrund der Komponente transparent machen&amp;quot;. Jedoch ist dies nicht die strenge Deutung der Opazität in Swing. Einige Komponenten, wie eine Drucktaste, können die &amp;quot;opaque&amp;quot; Eigenschaft auf false setzen, um der Komponente eine nicht-rechteckige Form zu geben oder Raum um die Komponente herum zu behalten für vorübergehende Sichtbarmachungen, wie eine Fokusanzeige. In diesen Fällen ist die Komponente nicht opaque, aber der Hauptteil seines Hintergrundes wird dennoch ganz ausgefüllt!&lt;br /&gt;
&lt;br /&gt;
Wie vorher definiert, ist die &amp;quot;opaque&amp;quot; Eigenschaft hauptsächlich ein Vertrag mit dem Repaintsystem. Wenn eine Komponente auch die &amp;quot;opaque&amp;quot; Eigenschaft benutzt, um zu definieren, wie Transparenz an den Sichtbarmachungen einer Komponente angewendet wird, dann sollte dieser Gebrauch von der Eigenschaft dokumentiert werden. (es kann für einige Komponenten vorzuziehen sein, zusätzliche Eigenschaften zu definieren, um die Sichtaspekte davon zu steuern, wie Transparenz angewendet wird. Z.B. hat javax.swing.AbstractButton die ContentAreaFilled Eigenschaft zu diesem Zweck.)&lt;br /&gt;
&lt;br /&gt;
Eine andere Frage, die eine Anmerkung wert ist, ist wie sich Opazität auf die Randeigenschaft einer Swingkomponente bezieht. Der Bereich, der durch ein Randobjekt auf einer Komponente dargestellt wird, wird noch als ein Teil der Geometrie dieser Komponente betrachtet. Das heißt, daß, wenn eine Komponente &amp;quot;opaque&amp;quot; ist, sie immer noch für das Füllen des Bereichs verantwortlich ist, der durch den Rand besetzt wird. (der Rand überlagert dann einfach seine Darstellung über die undurchlässige Komponente). &lt;br /&gt;
&lt;br /&gt;
Wenn eine dahinter liegende Komponente durch den Randbereich einer Komponente durchscheinen soll -- das heißt, wenn der Rand Transparenz unterstützt indem isBorderOpaque() &amp;quot;false&amp;quot; zurückgibt (z.B. EmptyBorder oder LineBorder mit roundedCorners) -- dann, muß die Komponente sich selbst auch als nicht opaque definieren und sicherstellen dass sie den Randbereich nicht übermalt.&lt;br /&gt;
&lt;br /&gt;
Siehe auch: http://forum.java.sun.com/thread.jspa?messageID=10329261&amp;amp;start=1&lt;br /&gt;
&lt;br /&gt;
===&amp;quot;optimiert&amp;quot; zeichnen===&lt;br /&gt;
Die Frage des Zeichnens von überlappenden Komponenten ist heikler. Selbst wenn keiner der direkten Geschwister einer Komponente diese überdeckt, ist es immer möglich, daß ein Nichtvorfahr Verwandter (wie ein &amp;quot;Vetter&amp;quot; oder &amp;quot;Tante&amp;quot;) sie verdecken könnte. In solch einem Fall könnte das repaint einer einzelnen Komponente innerhalb einer komplizierten Hierarchie eine Menge Treewalking erfordern, um &#039;korrektes&#039; Zeichnen sicherzustellen. Um unnötiges Durchqueren zu verringern, fügt Swing die read-only Eigenschaft &amp;quot;isOptimizedDrawingEnabled&amp;quot; zu javax.swing.JComponent hinzu: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public boolean isOptimizedDrawingEnabled()&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
die Einstellungen sind: &lt;br /&gt;
&lt;br /&gt;
* true: Die Komponente zeigt an, daß keine seiner direkten Kinder sich überlappen.&lt;br /&gt;
* false: Die Komponente gibt keine Garantie, ob seine direkten Kinder sich überlappen oder nicht.&lt;br /&gt;
&lt;br /&gt;
Indem es die Eigenschaft &amp;quot;isOptimizedDrawingEnabled&amp;quot; überprüft, kann Swing schnell seine Suche nach überlappenden Komponenten zur repaint Zeit eingrenzen.&lt;br /&gt;
&lt;br /&gt;
Da &amp;quot;isOptimizedDrawingEnabled&amp;quot; eine read-only Eigenschaft ist, ist also der einzige Weg, wie Komponenten den Default-Wert ändern können, die Klasse zu erweitern und diese Methode zu überschreiben, um den gewünschten Wert zurückzugeben. Alle standard Swingkomponenten geben &amp;quot;true&amp;quot; für diese Eigenschaft zurück, außer JLayeredPane, JDesktopPane und JViewPort. Wenn wir also z.B. ein JPanel mit einem Layout haben, das überlappende Komponenten zulässt (wie &amp;quot;OverlayLayout&amp;quot;), dann ist es gewöhnlich notwendig, JPanel zu erweitern und isOptimizedDrawingEnabled() zu überschreiben, um &amp;quot;false&amp;quot; zurückzugeben.&lt;br /&gt;
&lt;br /&gt;
==Die Malmethoden ==&lt;br /&gt;
Die Richtlinien, die auf AWTs lightweight Komponenten zutreffen, treffen auch auf Swingkomponenten zu -- zum Beispiel wird paint() aufgerufen, wenn es Zeit ist darzustellen -- außer daß Swing den paint() Aufruf in drei verschiedene Methoden unterteilt, die in folgender Reihenfolge aufgerufen werden: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    protected void paintComponent(Graphics g)&lt;br /&gt;
    protected void paintBorder(Graphics g)&lt;br /&gt;
    protected void paintChildren(Graphics g)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Swingprogramme sollten &#039;&#039;&#039;paintComponent()&#039;&#039;&#039; anstelle von paint() überschreiben. Obgleich die API es erlaubt, gibt es im Allgemeinen keinen Grund paintBorder() oder paintChildren() zu überschreiben (und wenn du es tust, sei dir sicher was du tust!). Dies macht es den Programmen einfacher, nur den Teil des Zeichnens zu überschreiben, den sie erweitern müssen. Z.B. löst dies das AWT Problem, das vorher erwähnt wurde, wo die Unterlassung, super.paint() aufzurufen alle lightweight Kinder am Erscheinen hinderte. &lt;br /&gt;
&lt;br /&gt;
Das SwingPaintDemo Programmbeispiel zeigt den einfachen Gebrauch der paintComponent() callback Methode von Swing:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/SwingPaintDemo.java SwingPaintDemo]&lt;br /&gt;
&lt;br /&gt;
===Das Malen und der UI Delegate ===&lt;br /&gt;
Die meisten standard Swingkomponenten haben ihren Look and Feel implementiert durch getrennte look-and-feel Objekte (genannt &amp;quot;UI Beauftragte&amp;quot;), für die steckbare Look and Feel Eigenschaft von Swing. Das heißt, daß das meiste oder das ganze Zeichnen der standard Komponenten dem UI Delegate übergeben wird und dies geschieht folgendermaßen: &lt;br /&gt;
&lt;br /&gt;
# paint() ruft paintComponent() auf. &lt;br /&gt;
# Wenn die &amp;quot;ui&amp;quot; Eigenschaft nicht &amp;quot;null&amp;quot; ist, ruft paintComponent() ui.update() auf. &lt;br /&gt;
# Wenn die &amp;quot;opaque&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist, füllt ui.update() den Hintergrund der Komponente mit der Hintergrundfarbe und ruft ui.paint() auf. &lt;br /&gt;
# ui.paint() stellt den Inhalt der Komponente dar. &lt;br /&gt;
&lt;br /&gt;
Das heißt, daß Unterklassen von Swingkomponenten, die einen UI Delegate haben (im Gegensatz zu direkten Unterklassen von JComponent), super.paintComponent() innerhalb ihrer paintComponent Überschreibung aufrufen sollten: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public class MyPanel extends JPanel {&lt;br /&gt;
        protected void paintComponent(Graphics g) {&lt;br /&gt;
	    // Let UI delegate paint first &lt;br /&gt;
	    // (including background filling, if I&#039;m opaque)&lt;br /&gt;
	    super.paintComponent(g); &lt;br /&gt;
	    // paint my contents next....&lt;br /&gt;
        }&lt;br /&gt;
    }&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn aus irgendeinem Grund die Erweiterung der Komponente nicht zulassen möchte, daß der UI Delegate  malt (wenn sie zum Beispiel die sichtbaren Elemente der Komponente vollständig ersetzt), kann sie den Aufruf von super.paintComponent() weglassen, aber sie ist dann für das Ausfüllen ihres eigenen Hintergrundes verantwortlich, wenn die &amp;quot;opaque&amp;quot; Eigenschaft &amp;quot;true&amp;quot; ist, wie im Abschnitt über die &amp;quot;opaque&amp;quot; Eigenschaft besprochen wurde.&lt;br /&gt;
&lt;br /&gt;
==Malverarbeitung ==&lt;br /&gt;
Swing verarbeitet &amp;quot;repaint&amp;quot; Anträge in einer etwas anderen Weise als AWT, obgleich das Resultat für den Anwendungsprogrammierer im Wesentlichen dasselbe ist -- paint() wird aufgerufen. Swing tut dies, um seine RepaintManager API zu unterstützen (wird später besprochen), sowie zur Verbesserung der Malleistung. In Swing kann das Malen zwei Wegen folgen, wie unten beschrieben: &lt;br /&gt;
&lt;br /&gt;
(a) Der Malantrag entsteht im ersten heavyweight Vorfahr (normalerweise JFrame, JDialog, JWindow oder JApplet): &lt;br /&gt;
&lt;br /&gt;
# der &amp;quot;event dispatching thread&amp;quot; ruft paint() für diesen Vorfahr auf, &lt;br /&gt;
# die Default-Implementierung von Container.paint() ruft rekursiv paint() auf allen lightweight Nachkommen auf, &lt;br /&gt;
# wenn die erste Swingkomponente erreicht wird, macht die Default-Implementierung von &#039;&#039;&#039;JComponent.paint()&#039;&#039;&#039; folgendes: &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der Komponente eingeschaltet, wandelt sie das Graphics Objekt um zu einem passenden offscreen Graphics.&lt;br /&gt;
## ruft paintComponent() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) &lt;br /&gt;
## ruft paintBorder() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) &lt;br /&gt;
## ruft paintChildren() auf (und übergibt offscreen Graphics, wenn &amp;quot;doubleBuffered&amp;quot;) welche die Eigenschaften &amp;quot;clip&amp;quot;, &amp;quot;opaque&amp;quot; und &amp;quot;optimizedDrawingEnabled&amp;quot; verwendet, um genau festzustellen, für welche Nachkommen, &amp;quot;paint()&amp;quot; rekursiv aufzurufen ist.&lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der Komponente eingeschaltet, kopiert sie das offscreen Bild auf die Komponente unter Benutzung des ursprünglichen onscreen Graphics Objektes.&lt;br /&gt;
&lt;br /&gt;
::ANMERKUNG: die JComponent.paint() Schritte #1 und #5 werden in den rekursiven Aufrufen von paint() übersprungen (in paintChildren(), beschrieben in Schritt #4) weil alle lightweight Komponenten innerhalb einer Swingfensterhierarchie dasselbe offscreen Bild für Doppelpufferung teilen. &lt;br /&gt;
&lt;br /&gt;
(b) Der Malantrag entsteht durch einen Aufruf von repaint() auf einer Erweiterung von javax.swing.JComponent: &lt;br /&gt;
# JComponent.repaint() registriert einen asynchronen repaint Antrag beim RepaintManager der Komponente, der invokeLater() benutzt, um einen Runnable entstehen zu lassen, der den Antrag später auf dem &amp;quot;event dispatching thread&amp;quot; verarbeitet.&lt;br /&gt;
# der Runnable wird auf dem &amp;quot;event dispatching thread&amp;quot; ausgeführt und er veranlasst den RepaintManager der Komponente, &#039;&#039;&#039;paintImmediately()&#039;&#039;&#039; auf der Komponente aufzurufen, die folgendes tut: &lt;br /&gt;
## verwendet das Cliprechteck und die Eigenschaften &amp;quot;opaque&amp;quot; und &amp;quot;optimizedDrawingEnabled&amp;quot;, um die &#039;root&#039;  Komponente festzustellen, von der aus der Malvorgang anfangen muß (um sich um Transparenz und möglicherweise überlappende Komponenten kümmern zu können). &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der &#039;root&#039; Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager vom &#039;root&#039; eingeschaltet, wandelt sie das Graphics Objekt um zu einem passenden offscreen Graphics.&lt;br /&gt;
## ruft paint() auf der &#039;root&#039; Komponente auf (was die JComponent.paint() Schritte #2-4 oben unter (a) durchführt), und verursacht so, daß alles unter dem &#039;root&#039; gemalt wird, was sich mit dem Cliprechteck überschneidet.   &lt;br /&gt;
## wenn die &amp;quot;doubleBuffered&amp;quot; Eigenschaft der &#039;root&#039; Komponente &amp;quot;true&amp;quot; ist und Doppelpufferung ist im RepaintManager der &#039;root&#039; Komponente eingeschaltet, kopiert sie das offscreen Bild auf die Komponente unter Benutzung des ursprünglichen onscreen Graphics Objektes.&lt;br /&gt;
&lt;br /&gt;
::ANMERKUNG: wenn mehrfache Aufrufe von repaint() auf einer Komponente oder irgendwelchen seiner Swingvorfahren auftreten, bevor der repaint Antrag verarbeitet wird, können jene mehrfachen Anträge in einen einzigen Callback von paintImmediately() auf der obersten Swingkomponente zusammengefasst werden, auf der repaint() aufgerufen wurde. Z.B. wenn ein JTabbedPane eine JTable enthält und beide Aufrufe von repaint() absenden, bevor irgendwelche anstehenden Anträge dieser Hierarchie verarbeitet werden, ist das Resultat ein einziger Aufruf von paintImmediately() auf dem JTabbedPane, was veranlasst, daß paint() auf beiden Komponenten durchgeführt wird.&lt;br /&gt;
&lt;br /&gt;
Das heißt, daß update() für SwingKomponenten nie aufgerufen wird.&lt;br /&gt;
&lt;br /&gt;
Obgleich repaint() einen Aufruf von paintImmediately() ergibt, gilt es nicht als &amp;quot;Malcallback&amp;quot; , und Malcode sollte nicht innerhalb einer paintImmediately() gesetzt werden. Tatsächlich gibt es im Allgemeinen überhaupt keinen Grund, paintImmediately() zu überschreiben.&lt;br /&gt;
&lt;br /&gt;
===Synchrones Zeichnen===&lt;br /&gt;
Wie im vorhergehenden Abschnitt beschrieben, dient paintImmediately() als Ausgangspunkt um einer einzelnen Swingkomponente zu sagen, sich zu malen und zu überprüfen, ob alles erforderliche Zeichnen passend geschieht. Diese Methode kann auch für synchrone Malanträge verwendet werden, wie sein Name andeutet, was manchmal bei Komponenten erfordert ist, die sicherstellen müssen, daß ihr Aussehen in Echtzeit mit ihrem internen Zustand &#039;Schritt hält&#039; (z.B. gilt dies für das JScrollPane während eines Rollvorgangs). &lt;br /&gt;
&lt;br /&gt;
Programme sollten diese Methode nicht direkt aufrufen, es sei denn, es gibt eine tatsächliche Notwendigkeit zum Zeichnen in Echtzeit. Das ist so, &#039;&#039;&#039;weil durch das asynchrone repaint() mehrfache überlappende Anträge leistungssteigernd zusammengefasst werden&#039;&#039;&#039;, während das bei Direktaufrufen von paintImmediately() nicht geschieht. Zusätzlich ist die Richtlinie für das Aufrufen dieser Methode, daß sie auf dem &amp;quot;event dispatching thread&amp;quot; aufgerufen werden muß; es ist keine API, die für den &amp;quot;multi-threading&amp;quot; Ihres Malcodes bestimmt ist! Für mehr Einzelheiten über das &amp;quot;single-threaded&amp;quot; Modell von Swing, siehe den archivierten Artikel &amp;quot;Threads and Swing&amp;quot; :&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/threads/threads1.html Threads and Swing]&lt;br /&gt;
&lt;br /&gt;
==Der RepaintManager ==&lt;br /&gt;
Der Zweck der Swingklasse &amp;quot;RepaintManager&amp;quot; ist, die Leistungsfähigkeit der repaint Verarbeitung auf einer Swing Containerhierarchie zu maximieren, und auch zur Implementierung des &amp;quot;revalidation&amp;quot; Mechanismus von Swing (letzteres wird das Thema für einen weiteren Artikel sein, siehe auch: [http://www.java-forum.org/de/viewtopic.php?p=431845#431845 Validierung mit Swing]). Sie implementiert den repaint Mechanismus, indem sie alle repaint Anträge von Swing Komponenten abfängt (also werden sie nicht mehr durch das AWT verarbeitet) und ihren eigenen Zustand beibehält in Bezug auf das, was aktualisiert werden muss (bekannt als &amp;quot;dirty regions&amp;quot;, also &amp;quot;verschmutzte Bereiche&amp;quot;). Schließlich benutzt sie invokeLater(), um die anstehenden Anträge auf dem &amp;quot;event dispatching thread&amp;quot; zu verarbeiten, wie im Abschnitt &amp;quot;Malverarbeitung&amp;quot; beschrieben (Option b). [Der RepaintManager wird eine Serie von Malanträgen möglichst zusammenfassen, wenn (und nur wenn) der &amp;quot;Anführer&amp;quot; der Serie mit invokeLater verschickt wurde, aber noch nicht auf dem EDT verarbeitet wurde.]&lt;br /&gt;
&lt;br /&gt;
Für die meisten Programme kann der RepaintManager als Teil des internen Systems von Swing angesehen werden und praktisch ignoriert werden. Jedoch liefert seine API den Programmen die Möglichkeit einer feineren Steuerung von bestimmten Aspekten des Zeichnens. &lt;br /&gt;
&lt;br /&gt;
===Der &amp;quot;gegenwärtige&amp;quot; RepaintManager ===&lt;br /&gt;
Der RepaintManager ist entworfen, um dynamisch ausgewechselt zu werden, obgleich es durch die Default-Implementierung eine einzige Instanz gibt. Die folgenden statischen Methoden lassen Programme auf den &amp;quot;gegenwärtigen&amp;quot; RepaintManager zugreifen und ihn ersetzen: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public static RepaintManager currentManager(Component c)&lt;br /&gt;
    public static RepaintManager currentManager(JComponent c)&lt;br /&gt;
    public static void setCurrentManager(RepaintManager aRepaintManager)&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Den &amp;quot;gegenwärtigen&amp;quot; RepaintManager ersetzen===&lt;br /&gt;
Ein Programm würde den RepaintManager global erweitern und ersetzen, indem es folgendes tut: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    RepaintManager.setCurrentManager(new MyRepaintManager());&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Du kannst dir RepaintManagerDemo ansehen als ein einfaches lauffähiges Beispiel für die Installation von einem RepaintManager, der Informationen ausdruckt über das, was neu gezeichnet wird:&lt;br /&gt;
&lt;br /&gt;
[http://java.sun.com/products/jfc/tsc/articles/painting/src/RepaintManagerDemo.java RepaintManagerDemo]&lt;br /&gt;
&lt;br /&gt;
Ein interessanterer Grund für das Erweitern und das Ersetzen des RepaintManagers wäre die Art und Weise zu verändern, wie repaint Anträge verarbeitet werden. Zur Zeit ist der interne Zustand, der durch die Default-Implementierung benutzt wird, um schmutzige Regionen aufzuspüren, &amp;quot;package privat&amp;quot; und folglich nicht durch Unterklassen zugänglich. Jedoch können Programme ihre eigenen Mechanismen für das Aufspüren von schmutzigen Regionen und für das Zusammenfassen von repaint Anträgen einführen, indem sie die folgenden Methoden überschreiben: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public synchronized void addDirtyRegion(JComponent c, int x, int y, int w, int h) &lt;br /&gt;
    public Rectangle getDirtyRegion(JComponent aComponent)&lt;br /&gt;
    public void markCompletelyDirty(JComponent aComponent) &lt;br /&gt;
    public void markCompletelyClean(JComponent aComponent) {&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die addDirtyRegion() Methode ist die, die aufgerufen wird, wenn repaint() auf einer Swingkomponente aufgerufen wird, und kann folglich angespannt werden, um alle repaint Anträge abzufangen. Wenn ein Programm diese Methode überschreibt (und nicht super.addDirtyRegion() aufruft), dann wird es dafür verantwortlich, invokeLater() zu benutzen, um einen Runnable auf die &amp;quot;EventQueue&amp;quot; zu setzen, der paintImmediately() auf einer passenden Komponente aufruft (Übersetzung: nicht für Leute mit schwachem Herzen).&lt;br /&gt;
&lt;br /&gt;
===Globale Steuerung der Doppelpufferung===&lt;br /&gt;
Der RepaintManager stellt eine API zur Verfügung, um die Doppelpufferung global zu ermöglichenden und zu sperren: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    public void setDoubleBufferingEnabled(boolean aFlag)&lt;br /&gt;
    public boolean isDoubleBufferingEnabled()&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Während der Verarbeitung eines Malvorgangs wird diese Eigenschaft innerhalb JComponent überprüft, um festzustellen, ob man einen offscreen Puffer für die Darstellung verwendet. Diese Eigenschaft hat den Default-Wert &amp;quot;true&amp;quot;, aber die Programme, die Doppelpufferung für alle Swingkomponenten global sperren möchten, können folgendes tun: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;    RepaintManager.currentManager(mycomponent).setDoubleBufferingEnabled(false);&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkung: da die Default-Implementierung von Swing einen einzigen RepaintManager instanziert, ist das &amp;quot;mycomponent&amp;quot; Argument irrelevant.&lt;br /&gt;
&lt;br /&gt;
==Swing Malrichtlinien ==&lt;br /&gt;
Swingprogramme sollten diese Richtlinien verstehen, wenn Malcode geschrieben wird: &lt;br /&gt;
&lt;br /&gt;
# Für Swingkomponenten wird immer &#039;&#039;paint()&#039;&#039; aufgerufen als Ergebnis sowohl von systemausgelösten als auch von anwendungsausgelösten Malanträgen; &#039;&#039;update()&#039;&#039; wird nie auf Swingkomponenten aufgerufen. &lt;br /&gt;
# Programme können einen zukünftigen Aufruf von &#039;&#039;paint()&#039;&#039; auslösen, indem sie &#039;&#039;repaint()&#039;&#039; aufrufen, aber sie sollten &#039;&#039;paint()&#039;&#039; nicht direkt aufrufen. &lt;br /&gt;
# Auf Komponenten mit komplizierter Ausgabe, sollte &#039;&#039;repaint()&#039;&#039; mit Argumenten aufgerufen werden, die nur das Rechteck, das aktualisieren muß, definieren, und nicht die keine-Argumente-Version, die die gesamte Komponente veranlasst, neu gezeichnet zu werden. &lt;br /&gt;
# Die Swing Implementierung von paint() unterteilt den Aufruf in 3 verschiedene callback Methoden:&lt;br /&gt;
#* &#039;&#039;paintComponent()&#039;&#039;:  Erweiterungen von Swingkomponenten, die ihren eigenen Malcode einführen möchten, sollten diesen Code innerhalb des Bereichs der Methode paintComponent() setzen (nicht innerhalb von paint()). &lt;br /&gt;
#* &#039;&#039;paintBorder()&#039;&#039; &lt;br /&gt;
#* &#039;&#039;paintChildren()&#039;&#039; &lt;br /&gt;
# Swing stellt zwei Eigenschaften vor, um die Malleistung zu maximieren: &lt;br /&gt;
#*&#039;&#039;opaque&#039;&#039;: malt die Komponente alle ihre Bits oder nicht? &lt;br /&gt;
#*&#039;&#039;optimizedDrawingEnabled&#039;&#039;: können irgendwelche der Kinder dieser Komponente sich überschneiden? &lt;br /&gt;
# Wenn die &#039;&#039;opaque&#039;&#039; Eigenschaft einer Swingkomponente auf &#039;&#039;true&#039;&#039; gesetzt wird, dann erklärt sie sich damit einverstanden, alle Bits zu malen, die innerhalb ihrer Grenzen enthalten sind (dies schließt das Löschen ihres eigenen Hintergrundes innerhalb von &#039;&#039;paintComponent()&#039;&#039; ein), andernfalls können Bilschirmunreinheiten auftreten.&lt;br /&gt;
# Das Setzen entweder von &#039;&#039;opaque&#039;&#039; oder &#039;&#039;optimizedDrawingEnabled&#039;&#039; auf &#039;&#039;false&#039;&#039; für eine Komponente verursacht mehr Verarbeitung bei jedem Malvorgang, folglich empfehlen wir vernünftigen Gebrauch von Transparenz und überlappenden Komponenten zu machen. &lt;br /&gt;
# Erweiterungen von Swingkomponenten, die &#039;&#039;UI Delegates&#039;&#039; haben (einschließlich &#039;&#039;JPanel&#039;&#039;), sollten gewöhnlich &#039;&#039;super.paintComponent()&#039;&#039; innerhalb ihrer eigenen &#039;&#039;paintComponent()&#039;&#039; Implementierung aufrufen. Da der &#039;&#039;UI Delegate&#039;&#039; die Verantwortung für das Löschen des Hintergrundes auf undurchlässigen Komponenten hat, kümmert er sich um #6.&lt;br /&gt;
# Swing unterstützt eingebaute Doppelpufferung über die &#039;&#039;doubleBuffered&#039;&#039; Eigenschaft von &#039;&#039;JComponent&#039;&#039;, und ihr Default-Wert ist &#039;&#039;true&#039;&#039; für alle Swingkomponenten, gleichwohl das Setzen auf &#039;&#039;true&#039;&#039; auf einem Swingcontainer den allgemeinen Effekt hat, sie für alle lightweight Nachkommen dieses Containers einzuschalten, unabhängig von ihren einzelnen Einstellungen.&lt;br /&gt;
# Es wird ausdrücklich empfohlen, daß Doppelpufferung für alle Swingkomponenten ermöglicht wird.  &lt;br /&gt;
# Komponenten, die komplizierte Ausgaben darstellen, sollten intelligenten Gebrauch vom Cliprechteck machen, um die Malvorgänge auf diejenigen zu beschränken, die sich mit dem Clipbereich schneiden.&lt;br /&gt;
&lt;br /&gt;
=Zusammenfassung =&lt;br /&gt;
Beide, AWT und Swing, liefern APIs, um es den Programmen einfach zu machen, ihren Inhalt korrekt am Bildschirm darzustellen. Obgleich wir empfehlen, daß Entwickler für die meisten GUI Bedürfnisse Gebrauch von Swing machen, ist es nützlich, AWTs Malmechanismus zu verstehen, weil derjenige von Swing darauf aufbaut.&lt;br /&gt;
&lt;br /&gt;
Um die beste Leistung von diesen APIs zu erhalten, müssen Anwendungsprogramme die Verantwortung dafür übernehmen, die in diesem Dokument umrissenen Richtlinien zu befolgen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;br /&gt;
[[Kategorie:Swing]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Benutzer_Diskussion:AndreUhres&amp;diff=5199</id>
		<title>Benutzer Diskussion:AndreUhres</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Benutzer_Diskussion:AndreUhres&amp;diff=5199"/>
		<updated>2012-12-30T06:34:15Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Korrektur bezüglich ActionListener&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Danke Marco13 für die Korrektur bezüglich ActionListener. Ich frage mich jetzt, wieso es vorher funktionieren konnte??&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Taschenrechner.jpg&amp;diff=5163</id>
		<title>Datei:Taschenrechner.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Taschenrechner.jpg&amp;diff=5163"/>
		<updated>2012-10-18T01:52:56Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: lud eine neue Version von „Datei:Taschenrechner.jpg“ hoch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5160</id>
		<title>Command (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5160"/>
		<updated>2012-10-15T14:17:45Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Command Design Pattern kapselt eine Anfrage als ein Objekt, so dass wir unsere Kunden mit unterschiedlichen Anfragen parametrieren können, Anfragen in einer Warteschlange oder einem Journal ablegen können, und aufhebbare Operationen unterstützen können.&lt;br /&gt;
&lt;br /&gt;
Das Command Design Pattern entkoppelt ein Objekt das eine Anfrage macht, von demjenigen der weiß, wie diese Anfrage auszuführen ist. Im Mittelpunkt dieser Entkopplung steht ein Kommando-Objekt, das einen Empfänger und eine Aktion (oder eine Reihe von Aktionen) kapselt. Ein Aufrufer (invoker) richtet eine Anfrage an ein Kommando-Objekt durch den Aufruf seiner execute()-Methode, die wiederum die Aktionen des Empfängers (receiver) aufruft. Aufrufer können mit unterschiedlichen Befehlen konfiguriert werden, auch dynamisch zur Laufzeit.&lt;br /&gt;
&lt;br /&gt;
Die Befehle können auch eine &amp;quot;undo&amp;quot;-Funktion unterstützen (rückgängig machen), indem sie eine undo()-Methode umsetzen, die das Empfänger-Objekt wieder in seinen vorherigen Zustand bringt, d.h. in den Zustand vor dem letzten Aufruf der Methode execute().&lt;br /&gt;
&lt;br /&gt;
Ein Makro-Kommando ist eine einfache Erweiterung eines Kommandos, so dass er mehrere Befehle aufrufen kann. Ebenso kann ein Makro-Kommando die undo-Funktion leicht unterstützen.&lt;br /&gt;
&lt;br /&gt;
Kommandos können auch für die Umsetzung von Transaktions- und Logging-Systemen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns zum Beispiel einen Empfänger &amp;quot;Prozessor&amp;quot; vor, der arithmetische Operationen durchführen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Prozessor&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private double resultat;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
   &lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Prozessor für arithmetische Operationen&lt;br /&gt;
    */&lt;br /&gt;
   public Prozessor(){&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Berechnung von arithmetischen Operationen, wobei das Resultat kumuliert wird.&lt;br /&gt;
    * Das aktuelle Resultat wird auf dem Bildschirm angezeigt &lt;br /&gt;
    * und kann mit Hilfe der Methode getResultat() abgefragt werden.&lt;br /&gt;
    * @param operator Addition=+, Substraktion=-, Multiplikation=* Division=/&lt;br /&gt;
    * @param operand eine Zahl vom Typ &amp;quot;double&amp;quot;&lt;br /&gt;
    */&lt;br /&gt;
   public void berechnung(final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            resultat += operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            resultat -= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            resultat *= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            resultat /= operand;&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      System.out.println(this);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public double getResultat()&lt;br /&gt;
   {&lt;br /&gt;
      return resultat;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot; &amp;quot; + operand + &amp;quot; = &amp;quot; + resultat;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Schnittstelle &amp;quot;Command&amp;quot; ermöglicht es, eine Aktion auf dem Prozessor auszuführen und rückgängig zu machen. Sie ist sehr einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//Die Schnittstelle Command wird von den Klassen Berechnung, Reset und MacroCommand umgesetzt.&lt;br /&gt;
public interface Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public void execute();&lt;br /&gt;
&lt;br /&gt;
   public void undo();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Berechnung&amp;quot; ist ein konkreter Befehl, der eine arithmetische Operation berechnet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//eine konkreter Befehl, der eine arithmetische Operation berechnet&lt;br /&gt;
public class Berechnung implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
&lt;br /&gt;
   public Berechnung(final Prozessor prozessor, final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(operator, operand);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;-&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;+&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;/&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;*&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot;&amp;quot; + operand;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Reset&amp;quot; ist auch ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
public class Reset implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private double resultat;&lt;br /&gt;
&lt;br /&gt;
   public Reset(final Prozessor prozessor)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      resultat = prozessor.getResultat();&lt;br /&gt;
      prozessor.berechnung(&amp;quot;-&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(&amp;quot;+&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Reset{&amp;quot; + resultat + &#039;}&#039;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;MacroCommand&amp;quot; kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.Arrays;&lt;br /&gt;
&lt;br /&gt;
public class MacroCommand implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Command[] commands;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein MacroCommand kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden.&lt;br /&gt;
    *&lt;br /&gt;
    * @param commands eine Reihe von Befehlen&lt;br /&gt;
    */&lt;br /&gt;
   public MacroCommand(final Command[] commands)&lt;br /&gt;
   {&lt;br /&gt;
      this.commands = commands;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = 0; i &amp;lt; commands.length; i++)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].execute();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = commands.length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].undo();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return Arrays.toString(commands);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Taschenrechner&amp;quot; ist ein Aufrufer von Befehlen; sie weiß, wie man Befehle ausführen und rückgängig machen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
public class Taschenrechner&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private List&amp;lt;Command&amp;gt; undoable;&lt;br /&gt;
   private int undoLevel;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Taschenrechner der Befehle ausführen und rückgängig machen kann.&lt;br /&gt;
    */&lt;br /&gt;
   public Taschenrechner()&lt;br /&gt;
   {&lt;br /&gt;
      undoable = new ArrayList&amp;lt;&amp;gt;(10);&lt;br /&gt;
      undoLevel = 0;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Den Befehl ausführen, der als Parameter übergeben wird.&lt;br /&gt;
    *&lt;br /&gt;
    * @param command&lt;br /&gt;
    */&lt;br /&gt;
   public void execute(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.print(&amp;quot;Berechnung: &amp;quot;);&lt;br /&gt;
      command.execute();&lt;br /&gt;
      addUndoable(command);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen rückgängig machen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void undo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;undo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(--undoLevel);&lt;br /&gt;
            commande.undo();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen wieder ausführen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void redo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;redo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;lt; undoable.size())&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(undoLevel++);&lt;br /&gt;
            commande.execute();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   //private Servicemethode:&lt;br /&gt;
   private void addUndoable(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      //die &amp;quot;undoable&amp;quot;-Liste dem aktuellen undoLevel anpassen:&lt;br /&gt;
      int count = undoable.size() - undoLevel;&lt;br /&gt;
      for (int i = 0; i &amp;lt; count; i++)&lt;br /&gt;
      {&lt;br /&gt;
         undoable.remove(undoable.size() - 1);&lt;br /&gt;
      }&lt;br /&gt;
      //den neuen Befehl hinzufügen:&lt;br /&gt;
      undoable.add(command);&lt;br /&gt;
      undoLevel = undoable.size();&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schließlich ist hier die Starter-Klasse, zum Testen unseres kleinen Taschenrechners, der dynamisch mit verschiedenen Befehlen konfigurierbar ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Demo&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Prozessor prozessor = new Prozessor();&lt;br /&gt;
      Taschenrechner taschenrechner = new Taschenrechner();&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;-&amp;quot;, 4));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;*&amp;quot;, 3));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, 14));&lt;br /&gt;
      double resultat = prozessor.getResultat();&lt;br /&gt;
      &lt;br /&gt;
      Command[] pi = new Command[]&lt;br /&gt;
      {&lt;br /&gt;
         new Reset(prozessor),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;+&amp;quot;, 103993),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;/&amp;quot;, 33102),&lt;br /&gt;
      };&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new MacroCommand(pi));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, resultat));&lt;br /&gt;
&lt;br /&gt;
      taschenrechner.undo(2);&lt;br /&gt;
      taschenrechner.redo(1);&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Reset(prozessor));&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Taschenrechner gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Taschenrechner.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5159</id>
		<title>Command (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5159"/>
		<updated>2012-10-15T13:50:12Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Command Design Pattern kapselt eine Anfrage als ein Objekt, so dass wir unsere Kunden mit unterschiedlichen Anfragen parametrieren können, Anfragen in einer Warteschlange oder einem Journal ablegen können, und aufhebbare Operationen unterstützen können.&lt;br /&gt;
&lt;br /&gt;
Das Command Design Pattern entkoppelt ein Objekt das eine Anfrage macht, von demjenigen der weiß, wie diese Anfrage auszuführen ist. Im Mittelpunkt dieser Entkopplung steht ein Kommando-Objekt, das einen Empfänger und eine Aktion (oder eine Reihe von Aktionen) kapselt. Ein Aufrufer (invoker) richtet eine Anfrage an ein Kommando-Objekt durch den Aufruf seiner execute()-Methode, die wiederum die Aktionen des Empfängers (receiver) aufruft. Aufrufer können mit unterschiedlichen Befehlen konfiguriert werden, auch dynamisch zur Laufzeit.&lt;br /&gt;
&lt;br /&gt;
Die Befehle können auch eine &amp;quot;undo&amp;quot;-Funktion unterstützen (rückgängig machen), indem sie eine undo()-Methode umsetzen, die das Empfänger-Objekt wieder in seinen vorherigen Zustand bringt, d.h. in den Zustand vor dem letzten Aufruf der Methode execute().&lt;br /&gt;
&lt;br /&gt;
Ein Makro-Kommando ist eine einfache Erweiterung eines Kommandos, so dass er mehrere Befehle aufrufen kann. Ebenso kann ein Makro-Kommando die undo-Funktion leicht unterstützen.&lt;br /&gt;
&lt;br /&gt;
Kommandos können auch für die Umsetzung von Transaktions- und Logging-Systemen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns zum Beispiel einen Empfänger &amp;quot;Prozessor&amp;quot; vor, der arithmetische Operationen durchführen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Prozessor&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private double resultat;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
   &lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Prozessor für arithmetische Operationen&lt;br /&gt;
    */&lt;br /&gt;
   public Prozessor(){&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Berechnung von arithmetischen Operationen, wobei das Resultat kumuliert wird.&lt;br /&gt;
    * Das aktuelle Resultat wir auf dem Bildschirm angezeigt &lt;br /&gt;
    * und kann mit der Methode getResultat() abgefragt werden.&lt;br /&gt;
    * @param operator Addition=+, Substraktion=-, Multiplikation=* Division=/&lt;br /&gt;
    * @param operand eine Zahl vom Typ &amp;quot;double&amp;quot;&lt;br /&gt;
    */&lt;br /&gt;
   public void berechnung(final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            resultat += operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            resultat -= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            resultat *= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            resultat /= operand;&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      System.out.println(this);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public double getResultat()&lt;br /&gt;
   {&lt;br /&gt;
      return resultat;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot; &amp;quot; + operand + &amp;quot; = &amp;quot; + resultat;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Schnittstelle &amp;quot;Command&amp;quot; ermöglicht es eine Aktion auf dem Prozessor auszuführen und rückgängig zu machen. Sie ist sehr einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//Die Schnittstelle Command wird von den Klassen MacroCommand, Berechnung und Reset umgesetzt.&lt;br /&gt;
public interface Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public void execute();&lt;br /&gt;
&lt;br /&gt;
   public void undo();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Klasse &amp;quot;Berechnung&amp;quot; ist ein konkreter Befehl, um eine arithmetische Operation zu berechnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//eine konkreter Befehl, um eine arithmetische Operation zu berechnen&lt;br /&gt;
public class Berechnung implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
&lt;br /&gt;
   public Berechnung(final Prozessor prozessor, final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(operator, operand);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;-&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;+&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;/&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;*&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot;&amp;quot; + operand;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Reset&amp;quot; ist auch ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
public class Reset implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private double resultat;&lt;br /&gt;
&lt;br /&gt;
   public Reset(final Prozessor prozessor)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      resultat = prozessor.getResultat();&lt;br /&gt;
      prozessor.berechnung(&amp;quot;-&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(&amp;quot;+&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Reset{&amp;quot; + resultat + &#039;}&#039;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;MacroCommand&amp;quot; kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.Arrays;&lt;br /&gt;
&lt;br /&gt;
public class MacroCommand implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Command[] commands;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein MacroCommand kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden.&lt;br /&gt;
    *&lt;br /&gt;
    * @param commands eine Reihe von Befehlen&lt;br /&gt;
    */&lt;br /&gt;
   public MacroCommand(final Command[] commands)&lt;br /&gt;
   {&lt;br /&gt;
      this.commands = commands;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = 0; i &amp;lt; commands.length; i++)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].execute();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = commands.length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].undo();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return Arrays.toString(commands);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Taschenrechner&amp;quot; ist ein Aufrufer von Befehlen; sie weiß, wie man Befehle ausführen und rückgängig machen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
public class Taschenrechner&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private List&amp;lt;Command&amp;gt; undoable;&lt;br /&gt;
   private int undoLevel;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Taschenrechner der Befehle ausführen und rückgängig machen kann.&lt;br /&gt;
    */&lt;br /&gt;
   public Taschenrechner()&lt;br /&gt;
   {&lt;br /&gt;
      undoable = new ArrayList&amp;lt;&amp;gt;(10);&lt;br /&gt;
      undoLevel = 0;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Den Befehl ausführen, der als Parameter übergebn wird.&lt;br /&gt;
    *&lt;br /&gt;
    * @param command&lt;br /&gt;
    */&lt;br /&gt;
   public void execute(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.print(&amp;quot;Berechnung: &amp;quot;);&lt;br /&gt;
      command.execute();&lt;br /&gt;
      addUndoable(command);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen rückgängig machen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void undo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;undo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(--undoLevel);&lt;br /&gt;
            commande.undo();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen wieder ausführen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void redo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;redo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;lt; undoable.size())&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(undoLevel++);&lt;br /&gt;
            commande.execute();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   //private Servicemethode:&lt;br /&gt;
   private void addUndoable(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      //die &amp;quot;undoable&amp;quot;-Liste dem aktuellen undoLevel anpassen:&lt;br /&gt;
      int count = undoable.size() - undoLevel;&lt;br /&gt;
      for (int i = 0; i &amp;lt; count; i++)&lt;br /&gt;
      {&lt;br /&gt;
         undoable.remove(undoable.size() - 1);&lt;br /&gt;
      }&lt;br /&gt;
      //den neuen Befehl hinzufügen:&lt;br /&gt;
      undoable.add(command);&lt;br /&gt;
      undoLevel = undoable.size();&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schließlich ist hier die Starter-Klasse, zum Testen unseres kleinen Taschenrechners, der dynamisch mit verschiedenen Befehlen konfigurierbar ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Demo&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Prozessor prozessor = new Prozessor();&lt;br /&gt;
      Taschenrechner taschenrechner = new Taschenrechner();&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;-&amp;quot;, 4));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;*&amp;quot;, 3));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, 14));&lt;br /&gt;
      double resultat = prozessor.getResultat();&lt;br /&gt;
      &lt;br /&gt;
      Command[] pi = new Command[]&lt;br /&gt;
      {&lt;br /&gt;
         new Reset(prozessor),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;+&amp;quot;, 103993),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;/&amp;quot;, 33102),&lt;br /&gt;
      };&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new MacroCommand(pi));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, resultat));&lt;br /&gt;
&lt;br /&gt;
      taschenrechner.undo(2);&lt;br /&gt;
      taschenrechner.redo(1);&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Reset(prozessor));&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Taschenrechner gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Taschenrechner.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5158</id>
		<title>Command (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Command_(Design_Pattern)&amp;diff=5158"/>
		<updated>2012-10-15T13:44:55Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Die Seite wurde neu angelegt: „Das Command Design Pattern kapselt eine Anfrage als ein Objekt, so dass wir unsere Kunden mit unterschiedlichen Anfragen parametrieren können, Anfragen in ein…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Command Design Pattern kapselt eine Anfrage als ein Objekt, so dass wir unsere Kunden mit unterschiedlichen Anfragen parametrieren können, Anfragen in einer Warteschlange oder einem Journal ablegen können, und aufhebbare Operationen unterstützen können.&lt;br /&gt;
&lt;br /&gt;
Das Command Design Pattern entkoppelt ein Objekt das eine Anfrage macht, von demjenigen der weiß, wie diese Anfrage auszuführen ist. Im Mittelpunkt dieser Entkopplung steht ein Kommando-Objekt, das einen Empfänger und eine Aktion (oder eine Reihe von Aktionen) kapselt. Ein Aufrufer (invoker) richtet eine Anfrage an ein Kommando-Objekt durch den Aufruf seiner execute()-Methode, die wiederum die Aktionen des Empfängers (receiver) aufruft. Aufrufer können mit unterschiedlichen Befehlen konfiguriert werden, auch dynamisch zur Laufzeit.&lt;br /&gt;
&lt;br /&gt;
Die Befehle können auch eine &amp;quot;undo&amp;quot;-Funktion unterstützen (rückgängig machen), indem sie eine undo()-Methode umsetzen, die das Empfänger-Objekt wieder in seinen vorherigen Zustand bringt, d.h. in den Zustand vor dem letzten Aufruf der Methode execute().&lt;br /&gt;
&lt;br /&gt;
Ein Makro-Kommando ist eine einfache Erweiterung eines Kommandos, so dass er mehrere Befehle aufrufen kann. Ebenso kann ein Makro-Kommando die undo-Funktion leicht unterstützen.&lt;br /&gt;
&lt;br /&gt;
Kommandos können auch für die Umsetzung von Transaktions- und Logging-Systemen verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Stellen wir uns zum Beispiel einen Empfänger &amp;quot;Prozessor&amp;quot; vor, der arithmetische Operationen durchführen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Prozessor&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private double resultat;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
   &lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Prozessor für arithmetische Operationen&lt;br /&gt;
    */&lt;br /&gt;
   public Prozessor(){&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Berechnung von arithmetischen Operationen, wobei das Resultat kumuliert wird.&lt;br /&gt;
    * Das aktuelle Resultat wir auf dem Bildschirm angezeigt &lt;br /&gt;
    * und kann mit der Methode getResultat() abgefragt werden.&lt;br /&gt;
    * @param operator addition=+, soustraction=-, multiplication=* division=/&lt;br /&gt;
    * @param operand un nombre réel du type &amp;quot;double&amp;quot;&lt;br /&gt;
    */&lt;br /&gt;
   public void berechnung(final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            resultat += operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            resultat -= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            resultat *= operand;&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            resultat /= operand;&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
      System.out.println(this);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public double getResultat()&lt;br /&gt;
   {&lt;br /&gt;
      return resultat;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot; &amp;quot; + operand + &amp;quot; = &amp;quot; + resultat;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Schnittstelle &amp;quot;Command&amp;quot; ermöglicht es eine Aktion auf dem Prozessor auszuführen und rückgängig zu machen. Sie ist sehr einfach:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//Die Schnittstelle Command wird von den Klassen MacroCommand, Berechnung und Reset umgesetzt.&lt;br /&gt;
public interface Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public void execute();&lt;br /&gt;
&lt;br /&gt;
   public void undo();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Klasse &amp;quot;Berechnung&amp;quot; ist ein konkreter Befehl, um eine arithmetische Operation zu berechnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//eine konkreter Befehl, um eine arithmetische Operation zu berechnen&lt;br /&gt;
public class Berechnung implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private String operator;&lt;br /&gt;
   private double operand;&lt;br /&gt;
&lt;br /&gt;
   public Berechnung(final Prozessor prozessor, final String operator, final double operand)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
      this.operator = operator;&lt;br /&gt;
      this.operand = operand;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(operator, operand);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      switch (operator)&lt;br /&gt;
      {&lt;br /&gt;
         case &amp;quot;+&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;-&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;-&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;+&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;*&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;/&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
         case &amp;quot;/&amp;quot;:&lt;br /&gt;
            prozessor.berechnung(&amp;quot;*&amp;quot;, operand);&lt;br /&gt;
            break;&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return operator + &amp;quot;&amp;quot; + operand;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Reset&amp;quot; ist auch ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
//ein konkreter Befehl, der den Prozessor zurücksetzt:&lt;br /&gt;
public class Reset implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Prozessor prozessor;&lt;br /&gt;
   private double resultat;&lt;br /&gt;
&lt;br /&gt;
   public Reset(final Prozessor prozessor)&lt;br /&gt;
   {&lt;br /&gt;
      this.prozessor = prozessor;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      resultat = prozessor.getResultat();&lt;br /&gt;
      prozessor.berechnung(&amp;quot;-&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      prozessor.berechnung(&amp;quot;+&amp;quot;, resultat);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Reset{&amp;quot; + resultat + &#039;}&#039;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;MacroCommand&amp;quot; kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.Arrays;&lt;br /&gt;
&lt;br /&gt;
public class MacroCommand implements Command&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Command[] commands;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein MacroCommand kann eine Reihe von Befehlen ausführen, die als Parameter übergeben werden.&lt;br /&gt;
    *&lt;br /&gt;
    * @param commands eine Reihe von Befehlen&lt;br /&gt;
    */&lt;br /&gt;
   public MacroCommand(final Command[] commands)&lt;br /&gt;
   {&lt;br /&gt;
      this.commands = commands;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void execute()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = 0; i &amp;lt; commands.length; i++)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].execute();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public void undo()&lt;br /&gt;
   {&lt;br /&gt;
      for (int i = commands.length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;
      {&lt;br /&gt;
         commands[i].undo();&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return Arrays.toString(commands);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Klasse &amp;quot;Taschenrechner&amp;quot; ist ein Aufrufer von Befehlen; sie weiß, wie man Befehle ausführen und rückgängig machen kann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
import java.util.ArrayList;&lt;br /&gt;
import java.util.List;&lt;br /&gt;
&lt;br /&gt;
public class Taschenrechner&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private List&amp;lt;Command&amp;gt; undoable;&lt;br /&gt;
   private int undoLevel;&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Ein Taschenrechner der Befehle ausführen und rückgängig machen kann.&lt;br /&gt;
    */&lt;br /&gt;
   public Taschenrechner()&lt;br /&gt;
   {&lt;br /&gt;
      undoable = new ArrayList&amp;lt;&amp;gt;(10);&lt;br /&gt;
      undoLevel = 0;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Den Befehl ausführen, der als Parameter übergebn wird.&lt;br /&gt;
    *&lt;br /&gt;
    * @param command&lt;br /&gt;
    */&lt;br /&gt;
   public void execute(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.print(&amp;quot;Berechnung: &amp;quot;);&lt;br /&gt;
      command.execute();&lt;br /&gt;
      addUndoable(command);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen rückgängig machen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void undo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;undo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;gt; 0)&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(--undoLevel);&lt;br /&gt;
            commande.undo();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /**&lt;br /&gt;
    * Die als Parameter übergebene Anzahl von Befehlen wieder ausführen.&lt;br /&gt;
    *&lt;br /&gt;
    * @param number&lt;br /&gt;
    */&lt;br /&gt;
   public void redo(final int number)&lt;br /&gt;
   {&lt;br /&gt;
      System.out.println(&amp;quot;redo(&amp;quot; + number + &amp;quot;):&amp;quot;);&lt;br /&gt;
      for (int i = 0; i &amp;lt; number; i++)&lt;br /&gt;
      {&lt;br /&gt;
         if (undoLevel &amp;lt; undoable.size())&lt;br /&gt;
         {&lt;br /&gt;
            Command commande = undoable.get(undoLevel++);&lt;br /&gt;
            commande.execute();&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   //private Servicemethode:&lt;br /&gt;
   private void addUndoable(final Command command)&lt;br /&gt;
   {&lt;br /&gt;
      //die &amp;quot;undoable&amp;quot;-Liste dem aktuellen undoLevel anpassen:&lt;br /&gt;
      int count = undoable.size() - undoLevel;&lt;br /&gt;
      for (int i = 0; i &amp;lt; count; i++)&lt;br /&gt;
      {&lt;br /&gt;
         undoable.remove(undoable.size() - 1);&lt;br /&gt;
      }&lt;br /&gt;
      //den neuen Befehl hinzufügen:&lt;br /&gt;
      undoable.add(command);&lt;br /&gt;
      undoLevel = undoable.size();&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und schließlich ist hier die Starter-Klasse, zum Testen unseres kleinen Taschenrechners, der dynamisch mit verschiedenen Befehlen konfigurierbar ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
package command;&lt;br /&gt;
&lt;br /&gt;
public class Demo&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Prozessor prozessor = new Prozessor();&lt;br /&gt;
      Taschenrechner taschenrechner = new Taschenrechner();&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;-&amp;quot;, 4));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;*&amp;quot;, 3));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, 14));&lt;br /&gt;
      double resultat = prozessor.getResultat();&lt;br /&gt;
      &lt;br /&gt;
      Command[] pi = new Command[]&lt;br /&gt;
      {&lt;br /&gt;
         new Reset(prozessor),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;+&amp;quot;, 103993),&lt;br /&gt;
         new Berechnung(prozessor, &amp;quot;/&amp;quot;, 33102),&lt;br /&gt;
      };&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new MacroCommand(pi));&lt;br /&gt;
      taschenrechner.execute(new Berechnung(prozessor, &amp;quot;+&amp;quot;, resultat));&lt;br /&gt;
&lt;br /&gt;
      taschenrechner.undo(2);&lt;br /&gt;
      taschenrechner.redo(1);&lt;br /&gt;
      &lt;br /&gt;
      taschenrechner.execute(new Reset(prozessor));&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Taschenrechner gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Taschenrechner.jpg]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Taschenrechner.jpg&amp;diff=5157</id>
		<title>Datei:Taschenrechner.jpg</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Taschenrechner.jpg&amp;diff=5157"/>
		<updated>2012-10-15T13:41:26Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5153</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5153"/>
		<updated>2012-10-13T07:04:39Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seine &#039;&#039;&#039;Polymorphie&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphie&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst. Der Begriff &amp;quot;abstrakter Obertyp&amp;quot; bietet zudem eine ideale Überleitung zur &#039;&#039;&#039;Polymorphie&#039;&#039;&#039;, die ja die Beziehungen zwischen Ober- und Untertypen beschreibt.&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
&lt;br /&gt;
http://www.java-forum.org/einfuehrungen-erste-schritte/117297-interfaces.html&lt;br /&gt;
. Dort wird als Beispiel der abstrakte Obertyp &amp;quot;Buyable&amp;quot; als &amp;quot;interface&amp;quot; vorgestellt, welches die abstrakte Methode &#039;&#039;&#039;public int getPrice();&#039;&#039;&#039; beinhaltet. Nach dem Prinzip der Polymorphie, sind alle konkreten Untertypen (zum Beispiel Computer, Auto, Bier, Apfel, Hund, ...) im abstrakten Obertyp &amp;quot;Buyable&amp;quot; gekapselt. Aus diesem Grund wird der abstrakte Obertyp in diesem Beitrag mit einer Schablone veranschaulicht, welche an einer bestimmten Stelle einen Ausschnitt (Loch) hat: über ein Objekt gelegt, macht sie an dieser &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; die &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039; sichtbar und versteckt alles andere.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5152</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5152"/>
		<updated>2012-10-13T07:03:20Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seine &#039;&#039;&#039;Polymorphie&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphie&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst. Der Begriff &amp;quot;abstrakter Obertyp&amp;quot; bietet zudem eine ideale Überleitung zur &#039;&#039;&#039;Polymorphie&#039;&#039;&#039;, der ja die Beziehungen zwischen Ober- und Untertypen beschreibt.&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
&lt;br /&gt;
http://www.java-forum.org/einfuehrungen-erste-schritte/117297-interfaces.html&lt;br /&gt;
. Dort wird als Beispiel der abstrakte Obertyp &amp;quot;Buyable&amp;quot; als &amp;quot;interface&amp;quot; vorgestellt, welches die abstrakte Methode &#039;&#039;&#039;public int getPrice();&#039;&#039;&#039; beinhaltet. Nach dem Prinzip der Polymorphie, sind alle konkreten Untertypen (zum Beispiel Computer, Auto, Bier, Apfel, Hund, ...) im abstrakten Obertyp &amp;quot;Buyable&amp;quot; gekapselt. Aus diesem Grund wird der abstrakte Obertyp in diesem Beitrag mit einer Schablone veranschaulicht, welche an einer bestimmten Stelle einen Ausschnitt (Loch) hat: über ein Objekt gelegt, macht sie an dieser &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; die &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039; sichtbar und versteckt alles andere.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Strategy_(Design_Pattern)&amp;diff=5151</id>
		<title>Strategy (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Strategy_(Design_Pattern)&amp;diff=5151"/>
		<updated>2012-10-13T06:26:06Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Strategy Design Pattern definiert eine Familie von Algorithmen, isoliert jeden einzelnen und macht ihn austauschbar unabhängig von den Clients, die ihn benutzen.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
Stell dir eine Person vor, die sich mit ihrem Namen vorstellt: &amp;quot;Hallo, ich bin [Name der Person]&amp;quot;. Zuerst spricht sie normal. Aber dann bemerkt sie, dass nicht alle zuhören und ändert sozusagen ihre &amp;quot;Strategie&amp;quot; indem sie durch ein Megaphon spricht. Der entsprechende Java Code könnte etwa so aussehen:&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
public class Beispiel {&lt;br /&gt;
&lt;br /&gt;
    public Beispiel() {&lt;br /&gt;
        Person person = new Person(&amp;quot;Peter&amp;quot;);&lt;br /&gt;
        String text = &amp;quot;&#039;Hallo, ich bin &amp;quot; + person.getName() + &amp;quot;&#039;&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        Talking talkingNormally = new TalkingNormally();&lt;br /&gt;
        person.setTalking(talkingNormally);&lt;br /&gt;
        person.talk(text);&lt;br /&gt;
&lt;br /&gt;
        Talking talkingMegaphone = new TalkingMegaphone();&lt;br /&gt;
        person.setTalking(talkingMegaphone);&lt;br /&gt;
        person.talk(text);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public static void main(final String args[]) {&lt;br /&gt;
        Beispiel test = new Beispiel();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
Mit &amp;quot;setTalking&amp;quot; wird die Sprechart der Person festgelegt, damit sie dann mit &amp;quot;talk&amp;quot; in der richtigen Art spricht. &amp;quot;Talking&amp;quot; ist ein Interface, das ebenfalls eine &amp;quot;talk&amp;quot;-Methode enthält. Das Interface wird von &amp;quot;TalkingNormally&amp;quot; und &amp;quot;TalkingMegaphone&amp;quot; implementiert, um die zwei Sprecharten zu konkretisieren. Die &amp;quot;talk&amp;quot;-Methode der &amp;quot;Person&amp;quot; delegiert einfach an das zuständige &amp;quot;Talking&amp;quot;-Objekt, damit die Person in der gewollten Art spricht:&lt;br /&gt;
[[Bild:Strategy.jpg]]&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
public class Person {&lt;br /&gt;
&lt;br /&gt;
    private final String name;&lt;br /&gt;
    private Talking talking;&lt;br /&gt;
&lt;br /&gt;
    public Person(final String name) {&lt;br /&gt;
        this.name = name;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public String getName() {&lt;br /&gt;
        return name;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void talk(final String text) {&lt;br /&gt;
        talking.talk(text);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    public void setTalking(final Talking talking) {&lt;br /&gt;
        this.talking = talking;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
public interface Talking {//oder alternativ eine abstrakte Klasse&lt;br /&gt;
&lt;br /&gt;
    public void talk(final String text);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
public class TalkingNormally implements Talking {&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void talk(final String text) {&lt;br /&gt;
        System.out.println(&amp;quot;Talking normally: &amp;quot; + text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
public class TalkingMegaphone implements Talking {&lt;br /&gt;
&lt;br /&gt;
    @Override&lt;br /&gt;
    public void talk(final String text) {&lt;br /&gt;
        System.out.println(&amp;quot;Talking with megaphone: &amp;quot; + text);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5150</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5150"/>
		<updated>2012-10-13T06:24:40Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich zeigen wir hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Java I/O&#039;&#039;&#039; Klassen sind übrigens auch nach dem Decorator-Prinzip aufgebaut. Wir finden dort zum Beispiel den abstrakten Obertyp &#039;&#039;&#039;InputStream&#039;&#039;&#039; mit den konkreten Untertypen FileInputStream, ByteArrayInputStream, ObjectInputStream, ... Die abstrakte Decorator-Klasse heißt &#039;&#039;&#039;FilterInputStream&#039;&#039;&#039;, die logischerweise auch von InputStream abgeleitet ist. Konkrete &amp;quot;Decorators&amp;quot; sind: PushbackInputStream, BufferedInputStream, DataInputStream, ... Man kann auch leicht eigene konkrete &amp;quot;Decorators&amp;quot; hinzufügen, etwa einen &amp;quot;LowercaseInputStream&amp;quot;, der alle Großbuchstaben in Kleinbuchstaben umwandelt...&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5149</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5149"/>
		<updated>2012-10-13T06:23:39Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn dadas Subjekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das Subjekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste vorhanden ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Design Patterns]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Kategorie:Design_Patterns&amp;diff=5148</id>
		<title>Kategorie:Design Patterns</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Kategorie:Design_Patterns&amp;diff=5148"/>
		<updated>2012-10-13T06:22:38Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Die Seite wurde neu angelegt: „Kategorie:Java“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Kategorie:Java]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5147</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5147"/>
		<updated>2012-10-13T06:12:37Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das das Subjekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das Subjekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste vorhanden ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=JTable_Druckfunktion_anpassen&amp;diff=5146</id>
		<title>JTable Druckfunktion anpassen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=JTable_Druckfunktion_anpassen&amp;diff=5146"/>
		<updated>2012-10-11T00:55:05Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Seit Java 1.5 wird das Drucken der JTable unterstützt.&lt;br /&gt;
&lt;br /&gt;
== [http://download.oracle.com/javase/6/docs/api/javax/swing/JTable.html#print%28%29 &#039;&#039;&#039;1. Die standard Druckfunktion&#039;&#039;&#039;] ==&lt;br /&gt;
&lt;br /&gt;
print()&lt;br /&gt;
&lt;br /&gt;
print(JTable.PrintMode)&lt;br /&gt;
&lt;br /&gt;
print(JTable.PrintMode, MessageFormat, MessageFormat)&lt;br /&gt;
&lt;br /&gt;
print(JTable.PrintMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;print(JTable.PrintMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean, PrintService)&#039;&#039;&#039; (seit 1.6)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;JTable.PrintMode.NORMAL&#039;&#039;&#039; druckt die JTable mit der aktuellen Grösse.&lt;br /&gt;
&#039;&#039;&#039;JTable.PrintMode.FIT_WIDTH&#039;&#039;&#039; verkleinert die JTable, wenn nötig, so daß alle Spalten auf eine Seite passen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Header und Footer Text&#039;&#039;&#039; kann hinzugefügt werden (ansonsten einfach null angeben);&lt;br /&gt;
im MessageFormat kann man als ArgumentIndex 0 für die Seitennummer angegeben:&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
new MessageFormat(&amp;quot;Page {0}&amp;quot;)&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit dem &#039;&#039;&#039;ersten boolean&#039;&#039;&#039; Parameter kann man angeben ob der &#039;&#039;&#039;Druckdialog&#039;&#039;&#039; angezeigt werden soll oder nicht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PrintRequestAttributeSet&#039;&#039;&#039; ermöglicht die direkte Angabe von Druckattributen.&lt;br /&gt;
&lt;br /&gt;
Wenn der &#039;&#039;&#039;zweite boolean&#039;&#039;&#039; true ist (empfohlen), wird während des Druckvorgangs&lt;br /&gt;
ein modaler &#039;&#039;&#039;Progressdialog&#039;&#039;&#039; angezeigt, mit Abbruchmöglichkeit.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Printservice&#039;&#039;&#039; (seit 1.6) ist der PrintService der zum Drucken benutzt werden soll, &lt;br /&gt;
oder &#039;&#039;&#039;null&#039;&#039;&#039; zum Drucken auf den Standarddrucker.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;2. Das Anpassen der Druckfunktion&#039;&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
Folgende Methode ist verfügbar für erweiterte Druckanforderungen:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;getPrintable(JTable.PrintMode, MessageFormat, MessageFormat)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Unten ist ein Demoprogramm das zeigt, wie man die JTable Druckfunktion anpassen kann.&lt;br /&gt;
Als Beispiel drucken wir einen Reportheader mit zwei Zeilen und Rand.&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;3. Das Tutorial von Sun&#039;&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
Ein sehr gutes Tutorial über das Drucken von Tabellen, mit weiteren Einzelheiten: [http://download.oracle.com/javase/tutorial/uiswing/misc/printtable.html How to Print Tables]&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;4. Demoprogramm das zeigt, wie man die JTable Druckfunktion anpassen kann&#039;&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:TableReportDemo1.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das Druckbild sieht dann etwa so aus (zwei Seiten): &lt;br /&gt;
&lt;br /&gt;
[[Datei:TableReportDemo2.jpg]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * TableReportDemo.java This demo shows you how to customize the JTable print&lt;br /&gt;
 * function. As an example, we print a report header with two rows and a border.&lt;br /&gt;
 */&lt;br /&gt;
import java.awt.*;&lt;br /&gt;
import java.awt.event.ActionEvent;&lt;br /&gt;
import java.awt.print.*;&lt;br /&gt;
import java.util.logging.Level;&lt;br /&gt;
import java.util.logging.Logger;&lt;br /&gt;
import javax.print.attribute.HashPrintRequestAttributeSet;&lt;br /&gt;
import javax.print.attribute.Size2DSyntax;&lt;br /&gt;
import javax.print.attribute.standard.MediaPrintableArea;&lt;br /&gt;
import javax.print.attribute.standard.MediaSize;&lt;br /&gt;
import javax.print.attribute.standard.MediaSizeName;&lt;br /&gt;
import javax.print.attribute.standard.OrientationRequested;&lt;br /&gt;
import javax.swing.*;&lt;br /&gt;
import javax.swing.table.DefaultTableModel;&lt;br /&gt;
&lt;br /&gt;
public final class TableReportDemo extends JFrame&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private JTable table;&lt;br /&gt;
   private JButton btPrint;&lt;br /&gt;
   private Action printAction = new AbstractAction(&amp;quot;Print...&amp;quot;)&lt;br /&gt;
   {&lt;br /&gt;
&lt;br /&gt;
      @Override&lt;br /&gt;
      public void actionPerformed(final ActionEvent e)&lt;br /&gt;
      {&lt;br /&gt;
         try&lt;br /&gt;
         {&lt;br /&gt;
            print(table, new Insets(15, 15, 15, 15), true);&lt;br /&gt;
         } catch (PrinterException ex)&lt;br /&gt;
         {&lt;br /&gt;
            Logger.getLogger(TableReportDemo.class.getName()).log(Level.SEVERE, null, ex);&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
   };&lt;br /&gt;
   private HashPrintRequestAttributeSet attr;&lt;br /&gt;
&lt;br /&gt;
   public TableReportDemo()&lt;br /&gt;
   {&lt;br /&gt;
      super(&amp;quot;TableReportDemo&amp;quot;);&lt;br /&gt;
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&lt;br /&gt;
      btPrint = new JButton();&lt;br /&gt;
      add(btPrint, BorderLayout.SOUTH);&lt;br /&gt;
      btPrint.setAction(printAction);&lt;br /&gt;
      add(new JScrollPane(createTable()), BorderLayout.CENTER);&lt;br /&gt;
      pack();&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public JTable createTable()&lt;br /&gt;
   {&lt;br /&gt;
      String[] title = new String[]&lt;br /&gt;
      {&lt;br /&gt;
         &amp;quot;Title A&amp;quot;, &amp;quot;Title B&amp;quot;, &amp;quot;Title C&amp;quot;, &amp;quot;Title D&amp;quot;, &amp;quot;Title E&amp;quot;, &amp;quot;Title F&amp;quot;, &amp;quot;Title G&amp;quot;, &amp;quot;Title H&amp;quot;, &amp;quot;Title I&amp;quot;&lt;br /&gt;
      };&lt;br /&gt;
      String[][] data = new String[][]&lt;br /&gt;
      {&lt;br /&gt;
      };&lt;br /&gt;
      DefaultTableModel model = new DefaultTableModel(data, title);&lt;br /&gt;
      table = new JTable(model);&lt;br /&gt;
      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);&lt;br /&gt;
      for (int i = 0; i &amp;lt; 50; i++)&lt;br /&gt;
      {&lt;br /&gt;
         model.addRow(new String[]&lt;br /&gt;
                 {&lt;br /&gt;
                    String.valueOf(i), &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;, &amp;quot;&amp;quot;&lt;br /&gt;
                 });&lt;br /&gt;
      }&lt;br /&gt;
      return table;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   private void print(final JTable table, final Insets insets, final boolean portrait) throws PrinterException&lt;br /&gt;
   {&lt;br /&gt;
      try&lt;br /&gt;
      {&lt;br /&gt;
         Printable printable = new TableReport(table);&lt;br /&gt;
         PrinterJob job = PrinterJob.getPrinterJob();&lt;br /&gt;
         job.setPrintable(printable);&lt;br /&gt;
         // create an attribute set to store attributes from the print dialog&lt;br /&gt;
         if (attr == null)&lt;br /&gt;
         {&lt;br /&gt;
            attr = new HashPrintRequestAttributeSet();&lt;br /&gt;
            float leftMargin = insets.left;&lt;br /&gt;
            float rightMargin = insets.right;&lt;br /&gt;
            float topMargin = insets.top;&lt;br /&gt;
            float bottomMargin = insets.bottom;&lt;br /&gt;
            if (portrait)&lt;br /&gt;
            {&lt;br /&gt;
               attr.add(OrientationRequested.PORTRAIT);&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
               attr.add(OrientationRequested.LANDSCAPE);&lt;br /&gt;
               leftMargin = insets.top;&lt;br /&gt;
               rightMargin = insets.bottom;&lt;br /&gt;
               topMargin = insets.right;&lt;br /&gt;
               bottomMargin = insets.left;&lt;br /&gt;
            }&lt;br /&gt;
            attr.add(MediaSizeName.ISO_A4);&lt;br /&gt;
            MediaSize mediaSize = MediaSize.ISO.A4;&lt;br /&gt;
            float mediaWidth = mediaSize.getX(Size2DSyntax.MM);&lt;br /&gt;
            float mediaHeight = mediaSize.getY(Size2DSyntax.MM);&lt;br /&gt;
            attr.add(new MediaPrintableArea(&lt;br /&gt;
                    leftMargin, topMargin,&lt;br /&gt;
                    (mediaWidth - leftMargin - rightMargin),&lt;br /&gt;
                    (mediaHeight - topMargin - bottomMargin), Size2DSyntax.MM));&lt;br /&gt;
         }            // display a print dialog and record whether or not the user cancels it&lt;br /&gt;
         boolean printAccepted = job.printDialog(attr);&lt;br /&gt;
         if (printAccepted)&lt;br /&gt;
         {// if the user didn&#039;t cancel the dialog&lt;br /&gt;
            job.print(attr);// do the printing&lt;br /&gt;
         }&lt;br /&gt;
      } finally&lt;br /&gt;
      {&lt;br /&gt;
         // possibly restore the original table state here&lt;br /&gt;
      }&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Runnable gui = new Runnable()&lt;br /&gt;
      {&lt;br /&gt;
&lt;br /&gt;
         @Override&lt;br /&gt;
         public void run()&lt;br /&gt;
         {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
               UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());&lt;br /&gt;
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex)&lt;br /&gt;
            {&lt;br /&gt;
               Logger.getLogger(&amp;quot;log&amp;quot;).log(Level.OFF, ex.getMessage());&lt;br /&gt;
            }&lt;br /&gt;
            new TableReportDemo().setVisible(true);&lt;br /&gt;
         }&lt;br /&gt;
      };&lt;br /&gt;
      //GUI must start on EventDispatchThread:&lt;br /&gt;
      SwingUtilities.invokeLater(gui);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class TableReport implements Printable&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private Printable tablePrintable;&lt;br /&gt;
   private PageFormat pageFormatJTable;&lt;br /&gt;
&lt;br /&gt;
   TableReport(final JTable table)&lt;br /&gt;
   {&lt;br /&gt;
      tablePrintable = table.getPrintable(JTable.PrintMode.FIT_WIDTH, null, null);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public int print(final Graphics graphics, final PageFormat pageFormat,&lt;br /&gt;
           final int pageIndex) throws PrinterException&lt;br /&gt;
   {&lt;br /&gt;
      Graphics2D g = (Graphics2D) graphics;&lt;br /&gt;
      int x1 = (int) pageFormat.getImageableX();&lt;br /&gt;
      int y1 = (int) pageFormat.getImageableY();&lt;br /&gt;
      int w1 = (int) pageFormat.getImageableWidth();&lt;br /&gt;
      int h1 = (int) pageFormat.getImageableHeight();&lt;br /&gt;
      if (pageFormatJTable == null)&lt;br /&gt;
      {&lt;br /&gt;
         pageFormatJTable = (PageFormat) pageFormat.clone();&lt;br /&gt;
         Paper paperJTable = pageFormatJTable.getPaper();&lt;br /&gt;
         if (pageFormatJTable.getOrientation() == PageFormat.PORTRAIT)&lt;br /&gt;
         {&lt;br /&gt;
            paperJTable.setImageableArea(x1, y1 + 60,//skip header area&lt;br /&gt;
                    w1, h1 - 90);//reserve space for header and footer&lt;br /&gt;
         }&lt;br /&gt;
         else&lt;br /&gt;
         {&lt;br /&gt;
            paperJTable.setImageableArea(y1 + 60, x1,//skip header area&lt;br /&gt;
                    h1 - 90, w1);//reserve space for header and footer&lt;br /&gt;
         }&lt;br /&gt;
         pageFormatJTable.setPaper(paperJTable);&lt;br /&gt;
      }&lt;br /&gt;
      String title = &amp;quot;Title&amp;quot;;&lt;br /&gt;
      String subtitle = &amp;quot;Subtitle&amp;quot;;&lt;br /&gt;
      Font f = g.getFont();&lt;br /&gt;
      g.setFont(g.getFont().deriveFont(15f));&lt;br /&gt;
      FontMetrics fm = g.getFontMetrics();&lt;br /&gt;
      g.drawString(title, x1 + (w1 - fm.stringWidth(title)) / 2, y1 + 15);&lt;br /&gt;
      g.setFont(f);&lt;br /&gt;
      fm = g.getFontMetrics();&lt;br /&gt;
      g.drawString(subtitle, x1 + (w1 - fm.stringWidth(subtitle)) / 2, y1 + 30);&lt;br /&gt;
      g.drawRect(x1, y1, w1, 40);&lt;br /&gt;
      String footer = &amp;quot;Page &amp;quot; + (pageIndex + 1);&lt;br /&gt;
      g.drawString(footer, x1 + (w1 - fm.stringWidth(footer)) / 2, y1 + h1 - 10);&lt;br /&gt;
      //print the table:&lt;br /&gt;
      Graphics gCopy = g.create();&lt;br /&gt;
      int retVal = tablePrintable.print(gCopy, pageFormatJTable, pageIndex);&lt;br /&gt;
      gCopy.dispose();&lt;br /&gt;
      //&lt;br /&gt;
      return retVal;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;br /&gt;
[[Kategorie:Swing]]&lt;br /&gt;
[[Kategorie:Java-Codeschnipsel]]&lt;br /&gt;
[[Kategorie:JTable]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5139</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5139"/>
		<updated>2012-10-05T11:25:20Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich zeigen wir hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Java I/O&#039;&#039;&#039; Klassen sind übrigens auch nach dem Decorator-Prinzip aufgebaut. Wir finden dort zum Beispiel den abstrakten Obertyp &#039;&#039;&#039;InputStream&#039;&#039;&#039; mit den konkreten Untertypen FileInputStream, ByteArrayInputStream, ObjectInputStream, ... Die abstrakte Decorator-Klasse heißt &#039;&#039;&#039;FilterInputStream&#039;&#039;&#039;, die logischerweise auch von InputStream abgeleitet ist. Konkrete &amp;quot;Decorators&amp;quot; sind: PushbackInputStream, BufferedInputStream, DataInputStream, ... Man kann auch leicht eigene konkrete &amp;quot;Decorators&amp;quot; hinzufügen, etwa einen &amp;quot;LowercaseInputStream&amp;quot;, der alle Großbuchstaben in Kleinbuchstaben umwandelt...&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5138</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5138"/>
		<updated>2012-10-05T10:09:51Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich zeigen wir hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
Die &#039;&#039;&#039;Java I/O&#039;&#039;&#039; Klassen sind übrigens auch nach dem Decorator-Prinzip aufgebaut. Wir finden dort zum Beispiel den abstrakten Obertyp &#039;&#039;&#039;InputStream&#039;&#039;&#039; mit den konkreten Untertypen FileInputStream, StringBufferInputStream, ByteArrayInputStream, ObjectInputStream, ... Die abstrakte Decorator-Klasse heißt &#039;&#039;&#039;FilterInputStream&#039;&#039;&#039;, die logischerweise auch von InputStream abgeleitet ist. Konkrete &amp;quot;Decorators&amp;quot; sind: PushbackInputStream, BufferedInputStream, DataInputStream, LineNumberInputStream, ... Man kann auch leicht eigene konkrete &amp;quot;Decorators&amp;quot; hinzufügen, etwa einen &amp;quot;LowercaseInputStream&amp;quot;, der alle Großbuchstaben in Kleinbuchstaben umwandelt...&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5137</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5137"/>
		<updated>2012-10-04T18:36:06Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich zeigen wir hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5136</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5136"/>
		<updated>2012-10-04T18:22:48Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzuzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich ist hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5135</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5135"/>
		<updated>2012-10-04T13:22:09Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich ist hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
Damit haben wir das Verhalten der Katze zur Laufzeit erweitert, ohne vorhandenen Code ändern zu müssen. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5134</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5134"/>
		<updated>2012-10-04T13:01:52Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;, schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;, fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich ist hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5133</id>
		<title>Decorator (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Decorator_(Design_Pattern)&amp;diff=5133"/>
		<updated>2012-10-04T12:56:11Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Die Seite wurde neu angelegt: „In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komp…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In unserer Designs ist es oft nützlich, das Verhalten eines Objektes zur Laufzeit zu erweitern, ohne vorhandenen Code ändern zu müssen. Wir können die Komposition und die Delegation benutzen, um neue Verhaltensweisen zur Laufzeit hinzufügen.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern fügt einem Objekt dynamisch Verantwortung hinzu. Zwecks Erweiterung der Funktionalität eines Objekts, bietet das Decorator Design Pattern eine flexible Alternative zur Vererbung.&lt;br /&gt;
&lt;br /&gt;
Das Decorator Design Pattern impliziert die Schaffung einer Reihe von Decorator-Klassen, welche die Komponenten umhüllen.&lt;br /&gt;
&lt;br /&gt;
* Decorator-Klassen sind vom gleichen Typ wie die Komponenten, die sie umhüllen (der Typ wird entweder durch Vererbung oder durch die Implementierung einer Schnittstelle festgelegt).&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; verändern das Verhalten ihrer Komponenten durch Hinzufügen neuer Features vor, nach oder anstelle von Aufrufen von Methoden der Komponente.&lt;br /&gt;
* Wir können eine Komponente mit einer beliebige Anzahl von &amp;quot;Decorators&amp;quot; umhüllen.&lt;br /&gt;
* Die &amp;quot;Decorators&amp;quot; sind transparent für den Kunden, sofern der Kunde auf dem abstrakten Obertyp der Komponente aufbaut, und nicht auf konkreten Untertypen. &lt;br /&gt;
&lt;br /&gt;
Nehmen wir zum Beispiel den abstrakten Obertyp &amp;quot;Pet&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private int age;&lt;br /&gt;
   private String species;&lt;br /&gt;
&lt;br /&gt;
   public Pet(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      this.age = age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public int age()&lt;br /&gt;
   {&lt;br /&gt;
      return age;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public String species()&lt;br /&gt;
   {&lt;br /&gt;
      return species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public void setSpecies(final String species)&lt;br /&gt;
   {&lt;br /&gt;
      this.species = species;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   public abstract String laut();&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String toString()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;Ich bin ein(e) &amp;quot; + species + &amp;quot;; ich bin &amp;quot; + age + &amp;quot; Jahre alt; ich kann &#039;&amp;quot; + laut() + &amp;quot;&#039; !&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und den konkrete Untertyp &amp;quot;Katze&amp;quot;, der von &amp;quot;Pet&amp;quot; abgeleitet ist:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class Katze extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public Katze(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
      super.setSpecies(getClass().getSimpleName());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return &amp;quot;miauen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir haben den Namen der konkreten Klasse in der Eigenschaft &amp;quot;species&amp;quot; der abstrakten Klasse &amp;quot;Pet&amp;quot; gespeichert (um zu vermeiden, dass wir uns zu einem späteren Zeitpunkt auf die konkrete Klasse &amp;quot;Katze&amp;quot; beziehen müssen).&lt;br /&gt;
&lt;br /&gt;
Um das Verhalten eines &amp;quot;Pet&amp;quot; zu erweitern, führen wir den abstrakten Decorator &amp;quot;PetBehavior&amp;quot; hinzu. Erinnern wir uns daran, dass der Decorator den gleichen Typ hat wie die Komponente, die er umhüllt. Das ist der Grund, weshalb wir ihn von &amp;quot;Pet&amp;quot; ableiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public abstract class PetBehavior extends Pet&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public PetBehavior(final int age)&lt;br /&gt;
   {&lt;br /&gt;
      super(age);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir verwirklichen den abstrakten &amp;quot;Decorator&amp;quot; durch die zwei konkreten Implementierungen &amp;quot;PetSchnurrend&amp;quot; und &amp;quot;PetFauchend&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetSchnurrend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetSchnurrend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, schnurren&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class PetFauchend extends PetBehavior&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   private final Pet pet;&lt;br /&gt;
&lt;br /&gt;
   public PetFauchend(final Pet pet)&lt;br /&gt;
   {&lt;br /&gt;
      super(pet.age());&lt;br /&gt;
      this.pet = pet;&lt;br /&gt;
      setSpecies(pet.species());&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   @Override&lt;br /&gt;
   public String laut()&lt;br /&gt;
   {&lt;br /&gt;
      return pet.laut() + &amp;quot;, fauchen&amp;quot;;&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beachten wir in diesen konkreten &amp;quot;Decorators&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
* die Anwesenheit der Eigenschaft &amp;quot;pet&amp;quot;, die sich auf die Komponente bezieht, die vom Decorator umhüllt wird.&lt;br /&gt;
* das Hinzufügen eines neuen Verhaltens in der Methode laut() nach dem Aufruf der Methode laut() der Komponente: &#039;&#039;&#039;return pet.laut() + &amp;quot;schnurren&amp;quot;, &#039;&#039;&#039; (in PetSchnurrend) und &#039;&#039;&#039;return pet.laut() + &amp;quot;fauchen&amp;quot;; &#039;&#039;&#039; (in PetFauchend)&lt;br /&gt;
&lt;br /&gt;
Schließlich ist hier die Startklasse der Anwendung &amp;quot;MeineTierschau&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;package tierschau;&lt;br /&gt;
&lt;br /&gt;
public class MeineTierschau&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
   public static void main(final String[] args)&lt;br /&gt;
   {&lt;br /&gt;
      Pet animal = new Katze(4);&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetSchnurrend(animal); //den Pet mit PetSchnurrend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
      animal = new PetFauchend(animal); //den Pet mit PetFauchend umhüllen&lt;br /&gt;
      System.out.println(animal);&lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Programm gibt die folgenden Zeilen auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren&#039; !&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;Ich bin ein(e) Katze; ich bin 4 Jahre alt; ich kann &#039;miauen, schnurren, fauchen&#039; !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Am Ende sehen wir, dass die Katze sowohl von PetSchnurrend als auch von PetFauchend umhüllt wurde. Auf diese Weise könnte sie mit einer beliebige Anzahl von Decorators umhüllt werden.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5132</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5132"/>
		<updated>2012-10-02T08:13:11Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5131</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5131"/>
		<updated>2012-10-01T09:01:28Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Änderung 5128 von AndreUhres (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5130</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5130"/>
		<updated>2012-10-01T09:00:53Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Änderung 5129 von AndreUhres (Diskussion) rückgängig gemacht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkung:&#039;&#039;&#039;&lt;br /&gt;
Ab Java 5 kann in der Klasse Reader geschrieben werden:&lt;br /&gt;
&#039;&#039;&#039;public void update (NewsPublisher newsPublisher)&#039;&#039;&#039;. &lt;br /&gt;
Dadurch kann die Umwandlung &#039;&#039;&#039;NewsPublisher newsPublisher = (NewsPublisher) s&#039;&#039;&#039; wegfallen. &lt;br /&gt;
In diesem Fall müssen wir jedoch auch die Definition der Klasse Reader anpassen: &#039;&#039;&#039;public class Reader implements Observer &amp;lt;NewsPublisher&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
und die Observer-Schnittstelle:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;public interface Observer &amp;lt;T&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public void update (T subject);&lt;br /&gt;
}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieses Prinzip ermöglicht es uns also, dynamisch Klassen zu definieren, die nur bestimmte Arten von Objekten akzeptieren. Das Feature wurde in Java 5 unter der Bezeichnung &amp;quot;Generics&amp;quot; eingeführt.&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5129</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5129"/>
		<updated>2012-09-30T12:39:46Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkung:&#039;&#039;&#039;&lt;br /&gt;
Ab Java 5 kann in der Klasse Reader geschrieben werden:&lt;br /&gt;
&#039;&#039;&#039;public void update (NewsPublisher newsPublisher)&#039;&#039;&#039;. &lt;br /&gt;
Dadurch kann die Umwandlung &#039;&#039;&#039;NewsPublisher newsPublisher = (NewsPublisher) s;&#039;&#039;&#039; wegfallen. &lt;br /&gt;
In diesem Fall müssen wir jedoch auch die Definition der Klasse Reader anpassen: &#039;&#039;&#039;public class Reader implements Observer &amp;lt;NewsPublisher&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
und die Observer-Schnittstelle:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;public interface Observer &amp;lt;T&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public void update (T subject);&lt;br /&gt;
}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieses Prinzip ermöglicht es uns also, dynamisch Klassen zu definieren, die nur bestimmte Arten von Objekten akzeptieren. Das Feature wurde in Java 5 unter der Bezeichnung &amp;quot;Generics&amp;quot; eingeführt.&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5128</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5128"/>
		<updated>2012-09-30T08:56:26Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bemerkung:&#039;&#039;&#039;&lt;br /&gt;
Ab Java 5 kann in der Klasse Reader geschrieben werden:&lt;br /&gt;
&#039;&#039;&#039;public void update (NewsPublisher newsPublisher)&#039;&#039;&#039;. &lt;br /&gt;
Dadurch kann die Umwandlung &#039;&#039;&#039;NewsPublisher newsPublisher = (NewsPublisher) s&#039;&#039;&#039; wegfallen. &lt;br /&gt;
In diesem Fall müssen wir jedoch auch die Definition der Klasse Reader anpassen: &#039;&#039;&#039;public class Reader implements Observer &amp;lt;NewsPublisher&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
und die Observer-Schnittstelle:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;public interface Observer &amp;lt;T&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
    public void update (T subject);&lt;br /&gt;
}&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieses Prinzip ermöglicht es uns also, dynamisch Klassen zu definieren, die nur bestimmte Arten von Objekten akzeptieren. Das Feature wurde in Java 5 unter der Bezeichnung &amp;quot;Generics&amp;quot; eingeführt.&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5127</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5127"/>
		<updated>2012-09-30T07:46:16Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
          String news = newsPublisher.getNews();&lt;br /&gt;
          System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5126</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5126"/>
		<updated>2012-09-28T06:46:04Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          if (s instanceof NewsPublisher)&lt;br /&gt;
          {&lt;br /&gt;
             NewsPublisher newsPublisher = (NewsPublisher) s;&lt;br /&gt;
             String news = newsPublisher.getNews();&lt;br /&gt;
             System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5125</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5125"/>
		<updated>2012-09-27T14:18:26Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          if (s instanceof NewsPublisher)&lt;br /&gt;
          {&lt;br /&gt;
             NewsPublisher newspaper = (NewsPublisher) s;&lt;br /&gt;
             String news = newspaper.getNews();&lt;br /&gt;
             System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if (this.news == null || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5124</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5124"/>
		<updated>2012-09-27T12:43:46Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse zum Starten der Anwendung. Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          if (s instanceof NewsPublisher)&lt;br /&gt;
          {&lt;br /&gt;
             NewsPublisher newspaper = (NewsPublisher) s;&lt;br /&gt;
             String news = newspaper.getNews();&lt;br /&gt;
             System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          // Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          // verschieden ist von dem Wert der Eigenschaft &amp;quot;news&amp;quot;.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.news == null &amp;amp;&amp;amp; news != null) || (this.news != null &amp;amp;&amp;amp; news == null) || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung der Meldung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt und er wird nicht mehr benachrichtigt, bis er sich wieder abonniert.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5123</id>
		<title>Observer (Design Pattern)</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Observer_(Design_Pattern)&amp;diff=5123"/>
		<updated>2012-09-27T09:46:55Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Die Seite wurde neu angelegt: „Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachter…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das Observer Design Pattern definiert eine Abhängigkeit zwischen einem Subjekt (auch bekannt als &amp;quot;der Beobachtbare&amp;quot; oder &amp;quot;Observable&amp;quot;) und mehreren Beobachtern, so dass, wenn das Subjekt seinen Zustand ändert, alle seine abhängigen Objekte (seine Beobachter) automatisch benachrichtigt und aktualisiert werden.&lt;br /&gt;
&lt;br /&gt;
Das Subjekt aktualisiert die Beobachter unter Verwendung eines öffentlichen Protokolls, das für alle Beobachter gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Diese Methode wird aufgerufen, wenn das beobachtete Objekt verändert wird.&lt;br /&gt;
        * Die Anwendung ruft die Subjekt-Methode notifyObservers auf&lt;br /&gt;
        * um allen Beobachtern mitzuteilen, dass das beobachtete Objekt geändert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void update(Subject s);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beobachter sind lose mit dem Subjekt verbunden ist, weil das Subjekt nichts über die Beobachter weiß, außer dass sie das &amp;quot;Observer&amp;quot;-Protokoll verwirklichen.&lt;br /&gt;
&lt;br /&gt;
Ein Objekt kann sich als ein Beobachter bei einem oder mehreren Subjekten anmelden, indem es ebenfalls ein öffentliches Protokoll benutzt, das für alle Subjekte gilt. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public interface Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Füge einen Beobachter zu der Liste der Beobachter dieses Objekts hinzu,&lt;br /&gt;
        * sofern der Beobachter nicht bereits in der Liste ist.&lt;br /&gt;
        */&lt;br /&gt;
       public void addObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Entferne einen Beobachter aus der Liste der Beobachter dieses Objekts.&lt;br /&gt;
        */&lt;br /&gt;
       public void deleteObserver(Observer o);&lt;br /&gt;
&lt;br /&gt;
       /**&lt;br /&gt;
        * Informiere alle Beobachter, dass dieses Objekt modifiziert wurde.&lt;br /&gt;
        */&lt;br /&gt;
       public void notifyObservers();&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Reihenfolge, in der Beobachter von der Subjekt-Methode &amp;quot;notifyObservers&amp;quot; informiert werden, wird in der Regel nicht definiert, auch sollte die Anwendung sich nicht auf eine bestimmte Reihenfolge verlassen.&lt;br /&gt;
&lt;br /&gt;
Für ein Subjekt ist es wichtig, die Beobachter nur dann zu benachrichtigen, wenn sich wirklich etwas verändert hat, sonst kann es zu einer endlosen Kette von Meldungen kommen, auch wenn sich nichts geändert hat.&lt;br /&gt;
&lt;br /&gt;
Hier ist ein Beispiel eines Beobachters und eines Subjekts, sowie einer Klasse, um die Anwendung zu starten.&lt;br /&gt;
Kurze Zusammenfassung der Anwendung: eine Nachrichtenagentur beginnt Nachrichten zu veröffentlichen. Man kann sich bei einer Agentur abonnieren und immer, wenn eine neue Nachricht veröffentlicht wurde, wird man darüber informiert. Man kann auch das Abonnement kündigen, wenn man nicht mehr benachrichtigt werden möchte. Die Personen, die sich abonnieren können, werden durch die Klasse &amp;quot;Reader&amp;quot; definiert (der Beobachter), und die Agentur durch die Klasse &amp;quot;NewsPublisher&amp;quot; (das Subjekt, der Beobachtbare oder Observable):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Reader implements Observer&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private final String name;&lt;br /&gt;
&lt;br /&gt;
       public Reader(final String name)&lt;br /&gt;
       {&lt;br /&gt;
          this.name = name;&lt;br /&gt;
&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void update(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          if (s instanceof NewsPublisher)&lt;br /&gt;
          {&lt;br /&gt;
             NewsPublisher newspaper = (NewsPublisher) s;&lt;br /&gt;
             String news = newspaper.getNews();&lt;br /&gt;
             System.out.println(&amp;quot;&#039;&amp;quot; + name + &amp;quot;&#039; hat diese Nachricht erhalten: &#039;&amp;quot; + news + &amp;quot;&#039;&amp;quot;);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void subscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.addObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void unsubscribe(final Subject s)&lt;br /&gt;
       {&lt;br /&gt;
          s.deleteObserver(this);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    import java.util.ArrayList;&lt;br /&gt;
    import java.util.List;&lt;br /&gt;
&lt;br /&gt;
    public class NewsPublisher implements Subject&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       private String news;&lt;br /&gt;
       private List observersList;&lt;br /&gt;
&lt;br /&gt;
       public NewsPublisher()&lt;br /&gt;
       {&lt;br /&gt;
          observersList = new ArrayList(10);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void addObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          if (!observersList.contains(observer))&lt;br /&gt;
          {&lt;br /&gt;
             observersList.add(observer);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void deleteObserver(final Observer observer)&lt;br /&gt;
       {&lt;br /&gt;
          observersList.remove(observer);&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       @Override&lt;br /&gt;
       public void notifyObservers()&lt;br /&gt;
       {&lt;br /&gt;
          for (int i = 0; i &amp;lt; observersList.size(); i++)&lt;br /&gt;
          {&lt;br /&gt;
             Observer observer = (Observer) observersList.get(i);&lt;br /&gt;
             observer.update(this);&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public String getNews()&lt;br /&gt;
       {&lt;br /&gt;
          return news;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       public void setNews(final String news)&lt;br /&gt;
       {&lt;br /&gt;
          / / Zuerst überprüfen wir, ob der Wert des &amp;quot;news&amp;quot;-Parameters&lt;br /&gt;
          / / verschieden von dem Wert der Eigenschaft &amp;quot;news&amp;quot; ist.&lt;br /&gt;
          if (this.news == null &amp;amp;&amp;amp; news == null)&lt;br /&gt;
          {&lt;br /&gt;
             return;&lt;br /&gt;
          }&lt;br /&gt;
          if ((this.news == null &amp;amp;&amp;amp; news != null) || (this.news != null &amp;amp;&amp;amp; news == null) || !this.news.equals(news))&lt;br /&gt;
          {&lt;br /&gt;
             this.news = news; //das Objekt wird verändert, ...&lt;br /&gt;
             notifyObservers(); //wir müssen also alle Beobachter darüber informieren!&lt;br /&gt;
          }&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    package observer;&lt;br /&gt;
&lt;br /&gt;
    public class Demo&lt;br /&gt;
    {&lt;br /&gt;
&lt;br /&gt;
       public static void main(final String[] args)&lt;br /&gt;
       {&lt;br /&gt;
          NewsPublisher newsPublisher = new NewsPublisher();&lt;br /&gt;
&lt;br /&gt;
          Reader reader1 = new Reader(&amp;quot;Franz&amp;quot;);&lt;br /&gt;
          reader1.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          Reader reader2 = new Reader(&amp;quot;Philip&amp;quot;);&lt;br /&gt;
          reader2.subscribe(newsPublisher);&lt;br /&gt;
&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Paul hat ein neues Auto gekauft.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          reader2.unsubscribe(newsPublisher);&lt;br /&gt;
          newsPublisher.setNews(&amp;quot;Pierre reist nach Deutschland.&amp;quot;);&lt;br /&gt;
       }&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Anwendung gibt dies auf der Konsole aus:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Philip&#039; hat diese Informationen erhalten: &#039;Paul hat ein neues Auto gekauft.&#039;&#039;&#039;&#039;&lt;br /&gt;
*&#039;&#039;&#039;&#039;Franz&#039; hat diese Informationen erhalten: &#039;Pierre reist nach Deutschland.&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beachten wir, dass Philip (im Gegensatz zu Franz) nicht die Information erhalten hat &#039;Pierre reist nach Deutschland.&#039;, weil er sein Abonnement vor der Veröffentlichung kündigte:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code=java&amp;gt;&lt;br /&gt;
    reader2.unsubscribe (newsPublisher);&lt;br /&gt;
&amp;lt;/code=java&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab diesem Zeitpunkt wurde Philip aus der Liste der Beobachter des Objekts &amp;quot;newsPublisher&amp;quot; entfernt.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Design Pattern]]&lt;br /&gt;
[[Kategorie:Gang of Four Pattern]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5042</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5042"/>
		<updated>2012-02-21T06:09:09Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Siehe auch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst. Der Begriff &amp;quot;abstrakter Obertyp&amp;quot; bietet zudem eine ideale Überleitung zum &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;, der ja die Beziehungen zwischen Ober- und Untertypen beschreibt.&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
&lt;br /&gt;
http://www.java-forum.org/einfuehrungen-erste-schritte/117297-interfaces.html&lt;br /&gt;
. Dort wird als Beispiel der abstrakte Obertyp &amp;quot;Buyable&amp;quot; als &amp;quot;interface&amp;quot; vorgestellt, welches die abstrakte Methode &#039;&#039;&#039;public int getPrice();&#039;&#039;&#039; beinhaltet. Nach dem Prinzip der Polymorphie, sind alle konkreten Untertypen (zum Beispiel Computer, Auto, Bier, Apfel, Hund, ...) im abstrakten Obertyp &amp;quot;Buyable&amp;quot; gekapselt. Aus diesem Grund wird der abstrakte Obertyp in diesem Beitrag mit einer Schablone veranschaulicht, welche an einer bestimmten Stelle einen Ausschnitt (Loch) hat: über ein Objekt gelegt, macht sie an dieser &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; die &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039; sichtbar und versteckt alles andere.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5041</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5041"/>
		<updated>2012-02-17T08:19:51Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst. Der Begriff &amp;quot;abstrakter Obertyp&amp;quot; bietet zudem eine ideale Überleitung zum &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;, der ja die Beziehungen zwischen Ober- und Untertypen beschreibt.&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
&lt;br /&gt;
http://www.java-forum.org/einfuehrungen-erste-schritte/117297-interfaces.html&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Schnittstellen.JPG&amp;diff=5040</id>
		<title>Datei:Schnittstellen.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Schnittstellen.JPG&amp;diff=5040"/>
		<updated>2012-02-14T10:13:21Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: hat eine neue Version von „Datei:Schnittstellen.JPG“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5039</id>
		<title>Datei:Benutzercode.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5039"/>
		<updated>2012-02-14T09:28:10Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: hat eine neue Version von „Datei:Benutzercode.JPG“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5038</id>
		<title>Datei:Paintable.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5038"/>
		<updated>2012-02-14T08:53:57Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: hat eine neue Version von „Datei:Paintable.JPG“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5035</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5035"/>
		<updated>2012-02-11T07:22:11Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Sprachgebrauch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst. Der Begriff &amp;quot;abstrakter Obertyp&amp;quot; bietet zudem eine ideale Überleitung zum &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;, der ja die Beziehungen zwischen Ober- und Untertypen beschreibt.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5034</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5034"/>
		<updated>2012-02-11T06:47:42Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Das Konzept der Schnittstellen in der Programmierung mit Java */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
==Sprachgebrauch==&lt;br /&gt;
&lt;br /&gt;
Das Wort &#039;&#039;&#039;Schnittstelle&#039;&#039;&#039; ist im Java-Sprachgebrauch überladen. Im vorliegenden Artikel hat es die Bedeutung von &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;. Daneben wird es aber auch oft als deutsche Übersetzung für das Java-Konstrukt &#039;&#039;&#039;interface&#039;&#039;&#039; benutzt. Einerseits macht das Sinn, da ein &amp;quot;interface&amp;quot; ja abstrakte Methoden enthält, andererseits passt es aber nur bedingt, weil eine &#039;&#039;&#039;abstrakte Basisklasse&#039;&#039;&#039; ebenfalls abstrakte Methoden enthält. Im vorliegenden Artikel werden deshalb die Begriffe &amp;quot;interface&amp;quot; und &amp;quot;abstrakte Basisklasse&amp;quot; unter dem allgemeineren Begriff &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; zusammengefasst.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5033</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5033"/>
		<updated>2012-02-09T10:39:15Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: /* Das Konzept der Schnittstellen in der Programmierung mit Java */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen. Dadurch ist der Benutzercode weniger anfällig für Veränderungen in den Einzelheiten der Implementierung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5032</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5032"/>
		<updated>2012-02-09T08:30:38Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Das Konzept der Schnittstellen in der Programmierung mit Java==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039; nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
In Java hängt das Konzept der Schnittstellen also eng zusammen mit den Begriffen &#039;&#039;&#039;abstrakte Methode&#039;&#039;&#039;, &#039;&#039;&#039;abstrakter Obertyp&#039;&#039;&#039; (Interface oder abstrakte Basisklasse) und &#039;&#039;&#039;Polymorphismus&#039;&#039;&#039;. Es ermöglicht das Programmieren zu den Schnittstellen, ohne Festlegung von konkreten Implementierungen.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5031</id>
		<title>Datei:Benutzercode.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5031"/>
		<updated>2012-02-09T02:09:06Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: hat eine neue Version von „Datei:Benutzercode.JPG“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5030</id>
		<title>Schnittstellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Schnittstellen&amp;diff=5030"/>
		<updated>2012-02-09T01:39:09Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Schnittstellen sind die Verbindung eines Objektes zum Benutzercode&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Schnittstellen==&lt;br /&gt;
&lt;br /&gt;
Schnittstellen sind die Verbindung eines Objektes zum Benutzercode. Dieser kann dann zu den Schnittstellen programmieren, ohne sich um die versteckte Implementierung des Objekts kümmern zu müssen:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Schnittstellen.JPG]]&lt;br /&gt;
&lt;br /&gt;
In [[Java|Java]] gibt es &#039;&#039;&#039;[[Methode_(Java)#abstrakte_Methoden|abstrakte Methoden]]&#039;&#039;&#039;, mit denen wir die Schnittstellen von ihrer Implementierung trennen können. Eine abstrakte Methode ist ein Methodenkopf ohne Rumpf. Sie wird mit &amp;quot;public/protected abstract&amp;quot; gekennzeichnet und kann in einem [[Interface_(Java)|Interface]] oder in einer [[abstrakte_Klasse_(Java)|abstrakten Basisklasse]] deklariert werden. Das Interface (oder die abstrakte Basisklasse) stellt dann seinerseits einen &#039;&#039;&#039;abstrakten Obertyp&#039;&#039;&#039; dar. Beispiel:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Paintable.JPG]]&lt;br /&gt;
&lt;br /&gt;
Wenn der deklarierte Typ einer Variablen vom abstrakten Obertyp ist, können wir seinen Polymorphismus nutzen, ohne uns um die konkreten Untertypen kümmern zu müssen. Die Objekte, die der Variablen zur Laufzeit zugewiesenen werden, können von irgendeinem Untertyp sein, über den der Benutzercode nichts wissen muss:&lt;br /&gt;
&lt;br /&gt;
[[Datei:Benutzercode.JPG]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Java]]&lt;br /&gt;
[[Kategorie:Java Grundlagen]]&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5029</id>
		<title>Datei:Paintable.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5029"/>
		<updated>2012-02-09T01:09:32Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: hat eine neue Version von „Datei:Paintable.JPG“ hochgeladen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Schnittstellen.JPG&amp;diff=5028</id>
		<title>Datei:Schnittstellen.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Schnittstellen.JPG&amp;diff=5028"/>
		<updated>2012-02-09T00:59:09Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5027</id>
		<title>Datei:Benutzercode.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Benutzercode.JPG&amp;diff=5027"/>
		<updated>2012-02-09T00:58:49Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5026</id>
		<title>Datei:Paintable.JPG</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Datei:Paintable.JPG&amp;diff=5026"/>
		<updated>2012-02-09T00:58:27Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Diskussion:JTable_mit_Buttons_in_Tabellenzellen&amp;diff=5022</id>
		<title>Diskussion:JTable mit Buttons in Tabellenzellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Diskussion:JTable_mit_Buttons_in_Tabellenzellen&amp;diff=5022"/>
		<updated>2012-01-29T08:54:54Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ich habe versucht, die Verarbeitung von JTable Buttons in der Klasse ButtonHandler etwas zu vereinfachen. Es fällt auf, dass der Ansatz noch so aufwändig ist. Die Komplikationen kommen einerseits dadurch, dass JTable keinen Renderer oder Editor für JButtons unterstützt (im Gegensatz zu ComboBoxes und CheckBoxes), andrerseits durch das für JTable untypische Erfordernis, mehrere Renderer oder Editor für eine Spalte zu erlauben. [[Benutzer:AndreUhres|AndreUhres]] 08:54, 29. Jan. 2012 (UTC)&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Diskussion:JTable_mit_Buttons_in_Tabellenzellen&amp;diff=5021</id>
		<title>Diskussion:JTable mit Buttons in Tabellenzellen</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Diskussion:JTable_mit_Buttons_in_Tabellenzellen&amp;diff=5021"/>
		<updated>2012-01-29T07:34:53Z</updated>

		<summary type="html">&lt;p&gt;AndreUhres: Die Seite wurde neu angelegt: „Ich habe versucht, die Verarbeitung von JTable Buttons in der Klasse ButtonHandler etwas zu vereinfachen. Es fällt auf, dass der Ansatz noch so aufwändig ist. D…“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ich habe versucht, die Verarbeitung von JTable Buttons in der Klasse ButtonHandler etwas zu vereinfachen. Es fällt auf, dass der Ansatz noch so aufwändig ist. Die Komplikationen kommen einerseits dadurch, dass JTable keinen Renderer oder Editor für JButtons unterstützt (im Gegensatz zu ComboBoxes und CheckBoxes), andrerseits durch das für JTable untypische Erfordernis, mehrere Renderer oder Editor für eine Spalte zu erlauben.&lt;/div&gt;</summary>
		<author><name>AndreUhres</name></author>
	</entry>
</feed>