Aufbau des Shops
Begonnen wird mit der zentralen Klasse einer jeden SalesPoint-Anwendung, dem Shop
. Es wird eine neue Klasse VideoShop
erzeugt, als Ableitung von Shop
.
Der Konstruktor von VideoShop
ruft den Konstruktor der Oberklasse durch den Befehl super()
auf. Außerdem wird gleich die Größe des Shopfensters angepasst. Der Einfachheit halber wurde eine Grösse von 640x480 mit den Koordinaten (0,0) gewählt. Es steht jedem frei, diese an die Bildschirmauflösung anzupassen.
package videoautomat; public class VideoShop extends Shop { public VideoShop() { super(); setShopFrameBounds(new Rectangle(0, 0, 640, 480)); } }
Hinweis: In diesem Beispiel des Videoautomaten wird jede Klasse in einer separaten Datei gespeichert. Die Klassen des Automaten werden zu einem Paket videoautomat
zusammengefasst. Klassen eines Pakets werden normalerweise in einem Verzeichnis gespeichert, das den Namen des Pakets trägt. Darüberhinaus muss am Anfang einer Klasse eine Zeile der Form: package paketname;
stehen, die aussagt, welchem Paket die Klasse angehört.
Um die Anwendung ausführen zu können, ist eine Klasse erforderlich, die die von der Java Virtual Machine zur Ausführung benötigte main-Methode implementiert. Zu diesem Zweck wird eine neue Klasse MainClass
angelegt. In der main-Methode wird eine Instanz von VideoShop
erzeugt, welche an die statische Methode Shop.setTheShop(Shop s)
übergeben wird. Dieser Aufruf bewirkt, dass die übergebene Instanz zur einzigen und global erreichbaren erhoben wird. Auf diese globale Instanz kann über die ebenfalls statische Methode Shop.getTheShop()
von überall aus zugegriffen werden. Das hier angewandte Entwurfsmuster Singleton ist insofern zweckmäßig, da über dieses einzelne Shopobjekt nahezu alle global benötigten Daten gekapselt werden können.
Hinweis: Statisch bedeutet, die Variable oder die Methode ist keine Eigenschaft der Instanz sondern eine Eigenschaft der Klasse selbst und ist somit unabhängig vom Zustand des Objektes. Shop.getTheShop()
ist statisch und kann auf der Klasse Shop
aufgerufen werden.
Eine statische Variable wird von allen Instanzen einer Klasse geteilt und kann z.B. genutzt werden, um die Anzahl der erzeugten Instanzen zu zählen oder Informationen zwischen ihnen auszutauschen. D.h. alle Instanzen haben Zugriff auf ein und die selbe Variable und können diese ungewollt überschreiben.
Der Einsatz von static
muss wohl bedacht sein, sonst können z.B. zwei unabhängige SalesPoint
s sich gegenseitig den aktuellen Bargeldbestand überschreiben, wenn dieser auf statische Weise gespeichert ist. Statische Variablen bergen also eine gewisse Gefahr und werden üblicher Weise für Konstanten verwendet, die für alle Instanzen gleich bleiben.
Zuletzt wird noch ein Aufruf ergänzt, der die Instanz von VideoShop
zur Ausführung bringt.
package videoautomat; public class MainClass { public static void main(String arqs[]) { VideoShop shop = new VideoShop(); Shop.setTheShop(shop); shop.start(); } }
Nun existiert bereits eine lauffähige Anwendung. Nach der erfolgreichen Übersetzung des Programms und der Ausführung von MainClass
öffnet sich das Shopfenster, so wie es durch das Framework vordefiniert ist.
Verhalten beim Beenden
Nach dem ersten Testen der Anwendung fällt sofort die erzwungene Speicherung beim Beenden ins Auge. Im realen Leben ist es sicherlich angebracht, den Nutzer zum Speichern aufzufordern, da andernfalls ein Datenverlust auftreten könnte. Die Programmiererin jedoch kann zumindest für die Dauer der Entwicklung darauf verzichten, da es sich spätestens nach 4-5 Testläufen als sehr lästig erweisen dürfte. Ein einfaches Überschreiben der Methode quit()
in der Klasse VideoShop
umgeht den Zwang:
public class VideoShop extends Shop { . . . public void quit() { if (shutdown(false)) { System.exit(0); } } }
Der Videoautomat
Die eigentliche Interaktion mit der Anwendung findet aber nicht über das Shopfenster statt, sondern über die Klasse SalesPoint
. In dieser Anwendung soll VideoAutomat
diese Klasse implementieren:
package videoautomat; public class VideoAutomat extends SalesPoint { public VideoAutomat() { super(VideoShop.CAPTION_AUTOMAT); setSalesPointFrameBounds(new Rectangle(0, 0, 640, 480)); } }
Wie man sieht, wird wiederum die Größe und Lage des Fensters, diesmal über die Methode setSalesPointFrameBounds(Rectangle r)
festgelegt. Außerdem erwartet der Konstruktor der Klasse SalesPoint
einen String, welcher als Identifikationsmerkmal dient und unter Anderem im Fensterrahmen angezeigt wird. Entsprechend muss auch beim Aufruf von super()
ein String übergeben werden.
Um die darzustellenden Strings leichter und an einer Stelle bearbeiten zu können, wird eine String-Konstante im VideoShop
zur Verfügung gestellt.
Wie man erkennen kann, wird diese Variable statisch verwendet und durch final
vor weiteren Änderungen geschützt.
public class VideoShop extends Shop { . . . public static final String CAPTION_AUTOMAT = "****** VIDEOAUTOMAT *** 24 H ******"; . . . }
Damit der Automat auch sichtbar ist, muss die Klasse VideoAutomat
instantiiert und beim Shop
angemeldet werden. Dazu wird folgende Zeile der main-Methode in MainClass
angefügt:
public class MainClass { public static void main(String arqs[]) { . . . shop.addSalesPoint(new VideoAutomat()); } }
Bei erneuter Übersetzung und Ausführung erscheint nun, zusätzlich zu dem Shopframe, der Videoautomat mit dessen Standard-FormSheet
.
Das Menü des Ladens
Damit nach dem Schließen des Videoautomaten die Anwendung nicht jedesmal neu gestartet werden muss, um diesen zu rekonstruieren, wird als nächster Schritt das Menü des Shopfensters erweitert.
Derzeit besteht das Menü des Videoladens aus den Untermenüs Shop, mit der Möglichkeit zum Speichern, Laden und Beenden der Anwendung und MultiWindow, in welchem gewählt werden kann, ob die verschiedenen Frames der Anwendung in separaten Fenstern oder in Registerkarten innerhalb des Shopfensters angezeigt werden sollen. Das Menü soll im Folgenden um einen Eintrag ergänzt werden, dessen Aktivierung eine neue Instanz der Klasse VideoAutomat
erzeugt und dem Videoladen hinzufügt.
Dafür muss die Methode createShopMenuSheet()
der Klasse VideoShop
überschrieben werden. Sie liefert wie der Name schon sagt das MenuSheet
des Ladens. Die Klasse MenuSheet
kapselt den Namen des Menüs, wie z.B. MultiWindow. Ein Menü kann darüberhinaus weitere MenuSheet
-Instanzen beinhalten - die Untermenüs. Außerdem kann eine MenuSheet
-Instanz Objekte der Klasse MenuSheetItem
beinhalten, diese sind ähnlich wie Buttons direkt mit einer Aktion verknüpft.
Im Beispiel wird zunächst das Standard-MenuSheet
des Ladens über den Aufruf super.createShopMenuSheet()
zurückgegeben. Diesem wird ein neues Untermenü zugeordnet, welchem zuvor eine neue Instanz von MenuSheetItem
zugefügt worden ist. Dem Konstruktor des Menüeintrags muss eine Implementation des Interface Action
übergeben werden.
public class VideoShop extends Shop { . . . protected MenuSheet createShopMenuSheet() { MenuSheet ms_default = super.createShopMenuSheet(); MenuSheet ms_new = new MenuSheet(MS_NEW); MenuSheetItem msi_automat = new MenuSheetItem(MSI_AUTOMAT, new Action() { public void doAction(SaleProcess p, SalesPoint sp) throws Throwable { addSalesPoint(new VideoAutomat()); } }); ms_new.add(msi_automat); ms_default.add(ms_new); return ms_default; } }
Hinweis: Das Interface Action
gehört dem Package sale
des Frameworks an und darf nicht mit javax.swing.Action
verwechselt werden.
Die zu implementierende Methode doAction(SaleProcess process, SalesPoint point)
des Interface definiert, was innerhalb der Aktion geschieht.
In diesem Fall erfolgt die Implementierung des Interfaces durch eine sogenannte anonyme Klasse. Alternativ kann eine neue Klasse erstellt werden, die eine doAction
Methode enthält. Die Verwendung anonymer Klassen erschwert die Lesbarkeit und Wiederverwendbarkeit des Quelltextes. Sie sollten nur verwendet werden, wenn ihr Inhalt nur einmal vorkommt oder
der Zugriff auf Methoden und Ressourcen schwierig ist, wenn sie als eigene Klasse implementiert sind. Später wird gezeigt, wie Action
-Klassen als
eigene wiederverwendbare Klassen genutzt werden können.
Im konkreten Fall hier wird in der doAction
-Methode einfach eine Instanz von VideoAutomat
erzeugt und mittels addSalesPoint(SalesPoint sp)
beim Laden angemeldet. Der Name des Untermenüs sowie der des Menüeintrags werden in der Klasse VideoShop
definiert.
public class VideoShop extends Shop { . . . public static final String MS_NEW = "Videoautomat"; public static final String MSI_AUTOMAT = "Start automat"; public static final String MSG_ACCESS = "Acces denied!!!"; }
Nach erneuter Übersetzung und Ausführung kann ein neuer Videoautomat über den entsprechenden Eintrag im Menü des Shopfensters gestartet werden.
Einleitung | Videokatalog und -bestand |