Entwurfsmuster
Last updated
Last updated
Entwurfsmuster (design patterns) sind Vorlagen zur Problemlösung. Für die Softwareentwicklung ist der Begriff Viererbande (Gang of Four, kurz GoF) ein Synonym für objektorientierte Entwurfsuster. Die GoF Autoren verwendeten in ihrem Buch nicht Java, sondern C++ und Smalltalk. Java Beispiele findet man unter java-design-patterns.
Gute Seite zum Thema: https://sourcemaking.com/design_patterns
Das Kompositum ist das zentrale Entwurfsmuster in der Java Swing API. Man kann damit komplexe Komponenten aus anderen Komponenten/Objekte zusammenstellen. Beim Aufbau von swing UIs wird daher oft von top-level, intermediate component und atomic components gesprochen.
A top-level container is a swing component with one only purpose, and that is to hold other swing components (with lower status). In Swing there are four top-level containers, but only three from those are used. They are JFrame, JApplet and JDialog. (JWindow is the fourth.) Each program using Swing must have atleast one top-level container, or else it won't work correctly. The most common is JFrame.
An intermediate container is a component with the purpose of making the placement of the atomic components more easy. Sometimes you can't see them, for example is JPanel an intermediate container that is invisible. Other intermediate containers are JTabbedPane and JScrollPane. The most frequently used and most flexible is the JPanel.
The third class of component, the atomic components, are the most basic components in Swing. For example are JButton, JTextField and JComboBox atomic components. Some atomic components exsist for no other reason than presenting information for the user (JLabel), some are only used to get input from the user (JButton, JCheckBox), some can do both (JTable, JTextField). What its true for every atomic component is that they can't hold any other components. All atomic components descend from the JComponent class. This means that every atomic component supports the standard features, for example tool tips and borders.
Listener sind allgegenwärtige Pattern in GUI-Programmen. Die GoF verwendete den Begriff Observer. Inzwischen wird dieses Verhaltensmuster meistens (event-)Listener genannt. In Java Programmen finden wir oft die Begriffe ActionListener oder PropertyChangeListener. Listener sind aber auch Synonyme für die Klassen, die einen konkreten Beobachter implementieren. Im Bild Observer1
bzw Observer2
.
Das Observer pattern hat also vier Akteure:
das abstrakte Subjekt/Observable und das konkrete Subjekt (z.B. ein Push-Button)
den abstrakten Beobachter/Observer/Listener (Interface) und den konkreten Beobachter
In awt ist der abstrakte Beobachter/Observer bereits definiert, als Interface java.awt.event.ActionListener
. Nur im konkreten Beobachter/Observer muß die Methode actionPerformed(ActionEvent e)
noch implementiert werden.
Die klassisch "altbackene" Implementierung für einen Observer sieht typischerweise so aus:
das Interface wird angegeben [1]
der Observer this
registriert/attach sich beim Subjekt (ein Push-Button) als Listener [2]
und implementiert die geforderte Methode actionPerformed
, bei der das Subjekt ermittelt werden muß [3]
Eine "moderne" Implementierung (ab Java 8) verwendet Lambdaausdrücke:
das Interface muss man nicht angeben und actionPerformed
muß nicht explizit implementieren
denn die Registrierung beim Subjekt enthält bereits den Code für die gewünschte Aktion
der Code ist daher kompakter und besser lesbar
Der PropertyChangeListener
ist ein weiteres Observermuster, das weit verbreitet ist. Zusammen mit SwingWorker zum Beispiel. SwingWorker werden für zeitaufwändige Aufgaben benutzt, damit die GUI nicht blockert und bedienbar bleibt, und damit die Zwischenergebnisse im GUI angezeigt werden. Die SwingWorker-Task/Loader läuft dabei in separaten Threads. Die notwendige Synchronisation mit dem GUI-Thread geschieht über property change events. Der SwingWorker schreibt Informationen über seinen Zustand in zwei Properties "progress" und "state". Und benachrichtigt den EDT(Event Dispatch Thread), wie der GUI-Thread auch genannt wird.
Das SwingWorker Beispiel aus Java 8 verwendet noch die klassische Implementierungart, wobei der ActionListener
direkt bei der Registrierung konstruiert wird::
Das Dokumentationsbeispiel im aktuellen Java stammt noch aus Java 6 und wurde seitdem nicht aktualisiert. Es sollte inzwischen so aussehen:
Im SwingSet3 beansbinding-1.2.1.jar
von SwingLabs gibt es eine Weterentwicklung als Alternative für einen PropertyChange Observer. Diese ist dann nützlich, wenn mehrere Properties durch GUI-Objekte repräsentiert werden. Beispielsweise
"state" durch Label status
für PENDING, STARTED, DONE
"progress" durch JProgressBar progressBar
die Registrierung beim Subject wird durch das binding zwischen property und ui-Objekt ersetzt
In Java kommt es sehr häufig vor, dass eine Schnittstelle/interface so weit wie möglich von einer (abstrakten) Klasse vorimplementiert wird. Dieses Vorgehen ist unter dem Namen Interface/Implementation-Pair bekannt.
Beispiele:
interface java.util.List<E>
und abstract class java.util.AbstractList<E>
interface javax.swing.Action
und abstract class javax.swing.AbstractAction
Java Code Calling a process