Für den Verleih sind Videos unerlässlich. Dazu ist es notwendig, einen Videokatalog zu erstellen und dem Automaten die Möglichkeit zu geben, Videos zum Verleih anzubieten. Zum Verwalten von Warenverzeichnissen bietet das Framework im Paket data das Interface Catalog an. Ein Katalog besitzt einen Namen, anhand dessen er eindeutig identifiziert werden kann, und enthält eine bestimmte Menge von Einträgen. Diese Einträge bestehen aus einem Schlüsselwert, über den auf das Item zugegriffen werden kann und aus einem dazugehörigen Wert. Dieser Wert kann einen beliebigen Inhalt - je nach Notwendigkeit - annehmen.

Catalog

Catalog wurde im Framework als Interface implementiert, so das es in späteren Anwendungen zum Beispiel möglich ist, auf eine Datenbank zuzugreifen. Dazu muß dieses Interface in einer neuen Klasse implementiert werden, welche die Daten in eine Datenbank abbildet. Da es hier jedoch nicht um Datenbankprogrammierung geht, wird für dieses Programm eine schon im Framework vorhandene Implementation des Catalog-Interfaces benutzt: CatalogImpl aus dem Paket data.ooimpl.

CatalogImpl

Um den Katalog der Videos anzulegen, werden zunächst die Pakete data und data.ooimpl in der Klasse VideoMachine importiert:


  import data.*;
  import data.ooimpl.*;
        

Dann wird der Katalog angelegt und beim Shop angemeldet. Dazu wird folgender Code in den Anweisungsteil des Konstruktors von VideoMachine unter super(); geschrieben:


  Catalog videoCatalog = new CatalogImpl("Video-Catalog");
  addCatalog(videoCatalog);
        

Die erste dieser Anweisungen erstellt dabei einen neuen Katalog mit dem Namen "Video-Catalog". Mit der addCatalog-Anweisung wird der gerade erzeugte Katalog in der globalen Katalogliste angemeldet und ist dort nun unter seinem Namen verfügbar. Katalog-Namen müssen unterscheidbar sein, d.h. es können niemals zwei Kataloge mit dem gleichen Namen in der globalen Katalogliste angemeldet sein.

Als nächstes soll der Katalog mit Videos gefüllt werden. Dazu gehören zu jedem Video ein Name, ein Einkaufs- und ein Verkaufspreis. Zu Demonstrationszwecken werden daher zunächst drei Arrays angelegt, die diese Daten enthalten. Auf diese Weise kann das eigentliche Hinzufügen der Videos zum Katalog später sehr einfach durch eine for-Schleife erledigt werden. Die folgenden Zeilen werden ebenfalls direkt unter super(); in den Konstruktor der Klasse VideoMachine eingefügt.


  String[] videos = { "Video 01", "Video 02", "Video 03", "Video 04",
                      "Video 05", "Video 06", "Video 07", "Video 08",
                      "Video 09", "Video 10" };
  int[]    buy    = { 5000, 5000, 5000, 5000,
                      5000, 4000, 4000, 4000,
                      3000, 3000 };
  int[]    sell   = { 4000, 4000, 4000, 4000,
                      3500, 3500, 3500, 3500,
                      3000, 3000 };
        

Videosortiment

Wie man feststellt, sind alle Preise in Pfennigen angegeben. Dies ist das im Framework verwendete Format. So werden Fließkomma-Zahlen und die damit verbundenen Ungenauigkeiten beim Rechnen vermieden.

Preise

Katalogeinträge sind durch das Interface CatalogItem definiert. Die einzige im Framework schon vorhandene Implementierung ist die abstrakte Klasse CatalogItemImpl. Ein Objekt dieser Klasse ist in der Lage, einen Namen und einen Wert vom Typ Value zu speichern.

CatalogItem[Impl]

Es treten jetzt zwei Probleme auf: Zum einen ist die CatalogItemImpl abstrakt, d.h. mindestens eine Methode wurde in dieser Klasse definiert, aber nicht implementiert. In diesem Fall handelt es sich um die Methode getShallowClone. Zum anderen ist in der Klasse nur die Speicherung eines Wertes zu einem Schlüssel im Katalog vorgesehen.

Um das erste Problem zu lösen wird die Klasse VideoCassette einfach von CatalogItemImpl abgeleitet und in ihr die Methode getShallowClone implementiert.


  import data.ooimpl.*;

  public class VideoCassette extends CatalogItemImpl
  {
  }
        

Das zweite Problem ist auch nicht schwer zu beseitigen. Als Wert wird kein einfacher Wert genommen, sondern eine Variable vom Typ QuoteValue. QuoteValue ist eine Implementierung des Value-Interfaces und besteht in diesem Fall aus zwei Werten: dem Einkaufspreis und dem Verkaufspreis. Diese müssen beim Erzeugen der Variable an den Konstruktor übergeben werden und ebenfalls vom Typ Value sein. Als konkrete Implementierung von Value wird hier IntegerValue verwendet.

QuoteValue

QuoteValue ist im Paket data enthalten. Daher wird folgende import-Anweisung in VideoCassette eingefügt:


  import data.*;  
        

Nun benötigt VideoCassette den beschriebenen Konstruktor. Dieser leitet lediglich die Parameter name und value an den Konstruktor der Oberklasse weiter.


  public VideoCassette(String name, QuoteValue value)
  {
    super(name, value);
  }
        

Weiterhin soll es möglich sein, den Wert einer VideoCassette zu verändern. Daher wird die setValue-Methode, die in CatalogItemImpl als protected markiert ist, überschrieben. Ein wichtiger Unterschied, neben weniger restriktiven Zugriffsrechten ist, daß der übergebende Parameter nun ein QuoteValue sein muß. So wird es unmöglich, z.B. einen IntegerValue in VideoCassette zu speichern.


  public void setValue(QuoteValue value)
  {
    super.setValue(value);
  }
        

Zuletzt folgt die Methode getShallowClone, wegen der die Klasse überhaupt erst angelegt wurde. Sie erzeugt eine Kopie der VideoCassette mit gleichem Namen und gleichem Wert.

 
  protected CatalogItemImpl getShallowClone()
  {
    return new VideoCassette(new String(getName()),
                             (QuoteValue)getValue().clone());
  }      
        

Zu beachten ist, daß beim Klonen von Objekten auch wirklich ein neues Objekt entsteht und nicht eine Variable, die auf des gleiche Objekt zugreift. Daher wird in der Methode ein neuer String für den Namen erzeugt und auch der Wert, den man über getValue erhält, geklont.

Klonen von Objekten

Nun wird die oben schon erwähnte for-Schleife am Ende des Konstruktors von VideoMachine eingefügt. In den Körper der Schleife muß nun der Code zum Einfügen der Katalogeinträge geschrieben werden.


  for (int i=0; i < videos.length; i++) {
    videoCatalog.add(new VideoCassette(
                       videos[i],
                       new QuoteValue(
                         new IntegerValue(buy[i]),
		         new IntegerValue(sell[i]))),
                     null);
  }
        

Videosortiment

Der erste Paramter der add-Anweisung ist der zum Katalog hinzuzufügende Eintrag. Der zweite Parameter ist der zu verwendene DataBasket, der hier nicht benötigt wird. Wird statt des Datenkorbes null übergeben, treten die Änderungen sofort in Kraft. Auf die Eigenschaften und Verwendungsmöglichkeiten eines DataBasket wird später eingegangen.

Nach dem Anlegen des Katalogs können Bestände geschaffen werden. Ein Bestand basiert immer auf einem Katalog. Ein Bestandseintrag basiert dementsprechend auf einem Katalogeintrag aus diesem Katalog. Daher gleichen sich auch die jeweiligen Schlüsselwerte der Bestände/Bestandseinträge mit denen der Kataloge/Katalogeinträge.

Bestände implementieren das Stock-Interface. Es gibt zwei grundlegende Arten von Beständen: CountingStock und StoringStock.

Stocks

CountingStocks verwalten zu jedem Bestandseintrag dessen Anzahl. Sie sind daher geeignet, Bestände zu speichern, in denen sich die jeweiligen Artikel, die zu einem CatalogItem gehören, nicht voneinander unterscheiden.

CountingStock

StoringStocks hingegen können zu jedem eingetragenen Artikel neben seiner Zugehörigkeit zu einem Eintrag im zugrunde liegenden Katalog noch spezielle Merkmale speichern.

StoringStock

Es ist leicht ersichtlich, daß es für "HOMECINEMA" nicht notwendig ist, jedes Video einzeln anzusprechen. Videos eines Namens unterscheiden sich nicht durch weitere Eigenschaften (wie z.B. die Farbe der Hülle). Es wird also für die Anwendung ein ContingStock benutzt. Eine einfache, jedoch hier völlig ausreichende Implementation des CountingStock-Interfaces ist CountingStockImpl. Es wird im folgenden ein Objekt vom Typ CountingStockImpl mit dem Namen "Video-Countingstock" und dem zugehörigen, gerade aufgebauten Katalog videoCatalog im Konstruktor von VideoMachine erzeugt. Dieser wird dann zur globalen Bestandsliste hinzugefügt.

CountingStockImpl


  CountingStock cs =
    new CountingStockImpl("Video-Countingstock",
                          (CatalogImpl)videoCatalog);
  addStock(cs);
        

Später wird es einen Manager geben, der vom Büro aus den Videobestand des Automaten verwalten kann. Da er jedoch noch nicht existiert, soll der Bestand zunächst mit Hilfe einer Zwischenlösung aufgefüllt werden. Der nun folgende Code wird später wieder entfernt werden:


  Iterator cassettes = videoCatalog.keySet(null).iterator();
  while(cassettes.hasNext()) {
    cs.add((String)cassettes.next(), 5, null);
  }
        

Es werden von jedem im Katalog verzeichneten Video fünf Stück in den Bestand aufgenommen. Dazu wird der add-Methode einfach der Name des Katalogeintrags, die Anzahl der hinzuzufügenden Videos und der zu verwendende Datenkorb (DataBasket) übergeben. Um mit dem Iterator arbeiten zu können, muß java.util.* importiert werden.


  import java.util.*;
        

Was nun noch fehlt, ist ein wenig Geld in der Kasse. Dazu wird analog zum obigen Vorgehen zunächst ein Katalog für die verwendeten Geldstücke und -scheine und dann ein dazu passender Bestand erzeugt.

Ein spezieller Katalog für Währungen ist im Framework eine Variable vom Typ Currency. Auch Currency ist ein Interface. Es wird die schon vorhandene Implementation CurrencyImpl verwendet. Diese hat den Vorteil, daß ein Katalog für Deutsche Mark nicht mühsam aufgebaut werden muß. Vielmehr existiert ein Konstruktor, der diese Arbeit abnimmt. Es wird im folgenden also ein Katalog mit dem Namen "DM" für die deutsche Währung im Konstruktor von VideoMachine angelegt und zur globalen Katalogliste hinzugefügt. Der Name ist dabei wirklich nur ein Name und hat nichts mit dem erzeugten Kataloginhalt zu tun.

Currency


  addCatalog(new CurrencyImpl("DM"));          
        

Der zugehörige Bestand ist vom Typ MoneyBag. Ein MoneyBag ist ein spezieller CountingStock, der für die Arbeit mit Geld gedacht ist. Auch MoneyBag ist ein Interface und MoneyBagImpl eine Implementation davon. Eine Variable dieses Typs soll nun der Münzschacht des "HOMECINEMA" werden:

MoneyBag


  MoneyBag coinSlot =
    new MoneyBagImpl("coin slot", (CurrencyImpl)getCatalog("DM"));
        

Der Konstruktor von MoneyBagImpl benötigt, wie man sieht, ähnliche Parameter wie CountingStockImpl: einen Namen und den zum Bestand gehörenden Katalog. Der Katalog wurde hier über seinen Namen mittels getCatalog aus der globalen Katalogliste herausgesucht und an den Konstruktor übergeben.

Als nächstes wird das Geld zum Bestand addiert und der Bestand zur globalen Stockliste hinzugefügt:


  coinSlot.add("1-Pfennig-Stueck", 100000, null);
  addStock(coinSlot);          
        

Wie man sieht, wird auch hier das zu addierende Geldstück einfach durch den Namen des zugehörigen CatalogItems identifiziert. Es werden 100.000 Pfennige, also 1.000 DM, in den Münzschacht als Wechselgeld getan. Da in diesem Programm kein Wert auf die Verteilung der einzelnen Geldstücke gelegt wird, reicht es einfach mit der kleinsten Einheit, also Pfennigen, zu arbeiten.

Damit sind alle notwendigen Kataloge und Bestände angelegt.

Hier der Quelltext der in diesem Kapitel geänderten Klassen:

Den Shop anlegen Das Angebot anzeigen

last modified on 09.04.2002
by ch17