Videoautomat - Der Grundaufbau

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 SalesPoints 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() {
            private static final long serialVersionUID = 5046442149116183402L;
            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.


previous EinleitungVideokatalog und -bestand next



by Thomas Ryssel