www.r-krell.de
Webangebot für Schule und Unterricht, Software, Fotovoltaik und mehr

Willkommen/Übersicht  >  Informatik  >   Informatik-Seite d)

Informatik mit Java

Teil d): Fuhrpark-Verwaltung

Die Überschriften a) bis c) verweisen auf vorhergehenden Seiten, die Überschriften d) bis h) auf nachfolgende Seiten.

a)  Grundlegendes zu Java, benötigte Software (inkl. Downloadadressen) und Installation
b)  Erste Java-Programme (u.a. Autorennen u. Aufzug) sowie Verweise (Links) auf fremde Java-Seiten
c)  Sortieren und Suchen in Java sowie grafische Oberflächen mit der Java-AWT

d)  Adressbuch- und Fuhrpark-Verwaltung sowie Datei-Operationen mit Java:


e)  Lineare Abstrakte Datentypen (Keller, Schlangen, Listen) und einige Anwendungen (z.B. Tiefen- und Breitensuche im Labyrinth)
f) Abstrakter Datentyp Baum ([binärer] Sortierbaum, Rechenbaum, Spielbaum)
g) Abstrakter Datentyp Graph (Adjazenzmatrix u. -listen, typische Fragestellungen, Tiefen- u. Breitensuche)
h) Bau eines Compilers Java -> 1_AMOR (Syntaxdiagramm, Scanner, Parser, Variablentabelle, Codeerzeuger)

Eine vollständige Übersicht aller Java-Seiten gibt's auf der Informatik-Hauptseite!


zum Seitenanfang / zum Seitenende

Vorwort

Adressbuch- und Fuhrpark-Verwaltung
sowie Dateioperationen mit Java



Das auf meiner Java-Seite c) Gelernte (nämlich der Umgang mit Reihungen einschließlich dem Suchen und Sortieren) wird jetzt auf ein anspruchsvolleres Projekt übertragen. Nicht mehr nur Reihungen einfacher Zahlen werden betrachtet, sondern es soll ein Adressbuch aufgebaut werden, in das man die Namen, Geburtstage, Anschriften und Telefonnummern von Bekannten und Freunden eintragen kann. Das Adressbuch muss natürlich nicht nur die Datensätze aufnehmen, sondern auch verwalten können: Gezieltes Suchen, Löschen u.ä. ist/sind gefordert.

Während die Schülerinnen und Schüler in meinem Unterricht an dem Adressbuch gearbeitet haben, habe ich gemerkt, dass z.T. sehr komfortabel zu bedienende, optisch anspruchsvolle Programme entstanden, die Programmierung dahinter oft aber nicht modernen Grundsätzen der Verwendung möglichst in sich abgeschlossener, wiederverwendbarer Module gehorchte. Andere Schülerinnen und Schüler taten sich mit dem Transfer des bei Zahlenreihen Gelernten schwer, so dass ich parallel zum nach wie vor recht selbstständig zu bearbeitenden Schülerprojekt „Adressbuch" die Verwaltung eines kleinen Fuhrparks im Unterricht erarbeitet und besprochen habe. Mit dem Fuhrpark-Musterprojekt sollten allgemeine Grundlagen vermittelt und Anregungen für die Übernahme entsprechender Techniken auf das Adressbuch-Projekt gegeben werden.

Da es natürlich wenig Spaß macht, bei jedem Programmstart alle Einträge neu über die Tastatur einzugeben, sollte auch auf die Festplatte oder eine Diskette abgespeichert werden bzw. von dort geladen werden können. Das erforderte einen Einschub über die Datei-Behandlung in Java. Dieser sowie verschiedene Entwicklungsstadien des Fuhrpark-Projekts sind im Folgenden durch einige Arbeitsblätter bzw. Beispielprogramme dokumentiert; später sollen Schülerprojekte folgen (wobei ein Schüler das Adressbuch direkt als Datenbank-Applikation geschrieben hat, und statt mit den 'normalen', nachstehend beschriebenen Dateioperationen per SQL-Befehlen aus Java auf eine entsprechende Datenbank zugreift).

Angemerkt werden muss noch, dass die Sicherheitsrichtlinien von Java nur Applikationen den Zugriff auf Diskette oder Festplatte erlauben, nicht aber Applets.


zum Seitenanfang / zum Seitenende

Vernünftige Klasseneinteilung für die Fuhrpark-Verwaltung



Bildschirmabdruck: Fuhrpark-Verwaltung, 1. VersionEin Fuhrpark besteht aus Autos. Die Verwaltung des Fuhrparks soll über eine grafische Benutzeroberfläche erfolgen. Entsprechend liegt es nahe, eigene Klassen für ein Auto, den ganzen Fuhrpark und die Benutzeroberfläche (GUI = graphical user interface) einzurichten. Während die Eigenschaften bzw. Datenfelder und benutzte Objekte den Klassen recht leicht zugeordnet werden können (ein Auto hat ein Kennzeichen, einen Hersteller, einen bestimmten km-Stand usw. - diese Daten gehören also in die Autoklasse; die Reihung zur Aufnahme mehrerer Autos gehört in die Fuhrpark-Klasse während Textfelder und Bildschirmknöpfe sicher Objekte sind, die in die GUI-Klasse gehören), war bei den Methoden schon mehr Nachdenken nötig. Ein Vorgang wie z.B. das Aufnehmen eines neuen Autos in den Fuhrpark, erfordert Aktionen in mehreren bzw. allen Klassen. In der Oberfläche befinden sich die Eingabefelder: hier wird auf den auslösenden Knopfdruck reagiert. Dann werden die gesammelten und eventuell noch konvertierten Daten an das Fuhrpark-Klasse bzw. das zur Laufzeit eingerichtete Fuhrpark-Objekt gemäß der Beschreibung der Fuhrpark-Klasse weiter gereicht (Klassen sind die Baupläne der Objekte). Im Fuhrpark wird ein passender Platz in der Reihung ausgesucht und die Anzahl der Autos erhöht. Die individuellen Auto-Daten müssen aber letztlich beim Auto eingetragen werden, also die Datenfelder eines Kfz-Objekts ändern, weswegen eine passende Methode der Kfz-Klasse aufgerufen werden muss. Zum Aufnehmen gibt es demnach Methoden in allen drei Klassen, die sich untereinander aufrufen. Um hier einem klaren Programmierstil zu erzwingen, sollten in jeden Fall explizite Methoden verwendet werden müssen und nicht einfach Datenfelder anderer Objekte/Klassen manipuliert werden können: Deshalb wurden die Datenfelder der Kfz- und Fuhrpark-Klasse als „private" deklariert und so fremdem Zugriff entzogen.

Grundsätzlich ist das ordentliche Aufteilen in Klassen schon früher geübt: so z.B. beim Sortieren (eine Klasse, die Zahlen verwaltet und die Arbeit macht, und die Oberflächenklasse mit der Benutzerschnittstelle - siehe meine Java-Seite c). Seit den ersten Java_Programmen wurde immer wieder auf eine ordentliche Klassen-Einteilung hingewiesen, so schon anfangs bei der „Grundsätzlichen Struktur von Java-Programmen" (besondere Startdatei) und in meinem Einführungstext (beides Java-Seite a)), bei Hochhaus, Autorennen und Aufzug - vgl. meine Java-Seite b) ! Trotzdem ist es offenbar leider nicht immer leicht und selbstverständlich, dass bei jedem neuen Projekt die eigentlich altbekannten Grundsätze auch beachtet und tatsächlich eingehalten werden.

Ein Arbeitsblatt mit dem Programmtext zu einer ersten Version der Fuhrpark-Verwaltung (passend zum oben gezeigten Bildschirmabdruck: noch ohne Dateien, aber mit einigen weiterführenden Aufgaben) kann hier als pdf-Datei angesehen bzw. mit rechtem Mausklick und „Ziel speichern unter.." herunter geladen und später in aller Ruhe gelesen werden:

Fuhrpark-Verwaltung, 1. Version:
java-kfzverw.pdf (58 kB)

Hier sind noch keine Methoden für's Suchen oder Sortieren angedeutet. Sonst müsste auch bereits beim einzelnen Kraftfahrzeug eine Vergleichsmethode implementiert werden.


Arbeitsblatt Dateien

zum Seitenanfang / zum Seitenende

Dateien in Java



Dateioperationen in Java werden über FileReader bzw. FileWriter vorgenommen, auf die BufferedReader/-Writer oder ObjectInput- bzw. -OutputStreams aufbauen. Im Unterricht wurden konkrete Beispiele genannt und programmiert; hier soll zunächst ohne weiteren Kommentar eine als pdf-Datei abrufbare Übersicht gegeben werden.

Typische Konstrukte für das Schreiben und Lesen von Dateien in Java:

java-dateiop.pdf (13 kB)

Im Unterricht 2003 habe ich übrigens auf die Dateien für einzelne Buchstaben und Zahlen (Typ 1, oberes Seitendrittel im Bild) ganz verzichtet und nur Dateien für Objekte eingeführt. Das reicht völlig und vermeidet Verwirrung. Ganz auf den Dateizugriff aus Java zu verzichten, um statt dessen nur eine Datenbank-Anbindung zu verwenden und dort die Informationen zu speichern und zu ordnen - dazu konnte ich mich noch nicht durchringen. Vermutlich ist der hier beschrittene Weg doch einfacher nach zu vollziehen und legt Grundlagen, die später für eine vernünftige Arbeit mit Datenbanken hilfreich sind.




zum Seitenanfang / zum Seitenende

Erweiterte Fuhrpark-Verwaltung



Bildschirmabdruck: Fuhrpark-Verwaltung, erweiterte Version
Hier folgt - zunächst nur mit dem Kommentar im Quelltext - das Java-Programm der um das Löschen, Suchen und das Speichern bzw. Laden erweiterten Fuhrpark-Verwaltung. Der Programmtext ist auch wieder als pdf-Datei erhältlich, aber auch nachstehend abgedruckt.

Anschließend gibt es eine kritische Anmerkung mit dem Vorschlag zu einem besseren Vorgehen als dem hier gezeigten.

Erweiterte Fuhrparkverwaltung (zum Herunterladen bzw. Ansehen im pdf_Format; trotzdem bitte unten den Verbesserungsvorschlag ansehen!):


java-kfzverw-dat.pdf (104 kB)



Erweiterte Fuhrparkverwaltung (Text nachfolgend abgedruckt):

Der Quelltext besteht aus vier Dateien, nämlich

  1. Kfz - Beschreibung eines Autos mit den notwendigen Methoden
  2. KfzFuhrpark - Verwaltung von bis zu 25 Autos in einer Reihung
  3. KfzGUI - grafische Oberfläche zur Verwaltung der Autos
  4. KfzStart - Start der grafischen Oberfläche als Application oder als Applet

  5. Verbesserungs-Vorschlag: vergleicheMit und Sortierkriterien




zum Seitenanfang / zum Seitenende


//Kfz-Verwaltung, Datei 1/4
//Java JDK 1.1.18 -- Krell 21.2.2002/5.3.2002
import java.io.*;  //für Serializable

public class Kfz implements Serializable //implements S.. für Datei-op.!
{
  
//Hier stehen die Daten, die ein (jedes) Auto beschreiben.
  //Das vorangestellte private sorgt dafür, dass nur die Methoden 
  //dieser Klasse auf die Daten zugreifen dürfen (verhindert Fehler)
  private String kennzeichen; // z.B. "D-AB 123"
  private String hersteller;  // z.B. "VW"
  private String typ;         // z.B. "Polo"
  private int baujahr;        // z.B. 1998
  private int kmStand;        // z.B. 42389
  
  
//Und hier kommen die Methoden, um die Daten zu ändern oder anzusehen:
  
  
public void merken (String nummer, String firma, String modell, 
    
int jahr, int fahrtstrecke)
    
//Beim Aufruf auto.merken ("D-CD 234","Opel","Astra",2001,10893)
    //werden die übergebenen Daten in die fünf Variablen eingetragen:
    {
      kennzeichen = nummer;
      hersteller = firma;
      typ = modell;
      baujahr = jahr;
      kmStand = fahrtstrecke;
    }
    
  
public String nennen ()
    
//Gibt eine Zeichenkette mit allen Daten des Autos aus
    {
      String daten = 
"Das Auto mit der Nr. '"+kennzeichen+"', ein "+
       hersteller+
" "+typ+" von "+baujahr+", ist bisher "+kmStand+
           
" km gelaufen.";
      
return (daten);
    }
  
  
public String nummer()
    
//Nennt nur das amtl. Kennzeichen des Autos, sonst nichts  
    {
      
return (kennzeichen);
    }  
    
  
public String hersteller()
    
//Nennt nur den Hersteller des Autos, sonst nichts  
    {
      
return (hersteller);
    }  
  
    
  
public int kmZahl ()
    
//Nennt nur den kmStand des Autos, sonst nichts
    {
      
return (kmStand);
    }
    
  
public void neuerStand (int km)
    
//Ändert nur den kmStand des Autos, sonst nichts
    {
      kmStand = km;
    }      
    
  
public void kopiereVon (Kfz anderesAuto)
    
//Kopiert alle Daten vom anderen Auto in eigene Daten
    {       
      
kennzeichen = anderesAuto.kennzeichen;
      hersteller  = anderesAuto.hersteller;
      typ         = anderesAuto.typ;
      baujahr     = anderesAuto.baujahr;
      kmStand     = anderesAuto.kmStand;
    }    
}    




zum Seitenanfang / zum Seitenende


//Kfz-Verwaltung, Datei 2/4
//Java JDK 1.1.18 -- Krell 21.2.2002/5.3.2002
import java.io.*;

//Erzeugt und verwaltet Reihung fuhrpark aus 25 Objekten der Klasse Kfz
public class KfzFuhrpark
{
  
//Daten des Fuhrparks
  private Kfz[] fuhrpark = new Kfz[25]; //(bis zu) 25 Autos im Fuhrpark
  private int anzahlDerAutos = 0; //zunächst ist noch kein Auto bekannt.
    //Erlaubt ist/sind 0 <= anzahlDerAutos <= 25
  
  
//Methoden zur Verwaltung des Fuhrparks

  
public KfzFuhrpark() //Automatische Initialisierung
  {
    
for (int i=0; i<25; i++)
    {
      fuhrpark[i] = 
new Kfz(); //Erzeugen der 25 Objekte vom Typ Kfz
    }
  }    
  
  
public int wagenAnzahl () //Sagt, wie viele Autos es gibt
  {
    
return (anzahlDerAutos);
  }  

  
public void neuesAuto (String nummer, String produzent, String modell, 
    
int jahr, int kmStand) //Erweitert fuhrpark um das angegebene Auto
  {  
    fuhrpark[anzahlDerAutos].merken (nummer,produzent,modell,jahr,kmStand);
      
//Speichert Daten im fuhrpark an der indizierten Stelle durch Aufruf
      //der Kfz-Methode merken. Jede der 25 fuhrpark-Komponenten ist ein Kfz!
    anzahlDerAutos = anzahlDerAutos + 1;
      
//Durch die Neuaufnahme hat sich die Zahl der Autos um 1 erhöht!
  }   
     
  
public String ändereKmStand (String amtlKennzeichen, int neueKm)
  
//Ändert den kmStand des Autos mit dem angeg. Kennzeichen
  {      
     String meldung = 
"Auto "+amtlKennzeichen
                        +
" nicht gefunden -- km-Zahl nicht geändert";
     //Finden des Index i vom Auto mit der gesuchten Nummer
     int i = anzahlDerAutos - 1; //von hinten beginnen
     while ((i>=0)&&(! fuhrpark[i].nummer().equals(amtlKennzeichen)))
     {          
//equals statt == , da versch. Objekte mit gleichem Inhalt
       i = i-1;  
     }  
     
//KmStand ändern
     if (i>=0) //Auto gefunden -- sonst ist i = -1
     {
       fuhrpark[i].neuerStand (neueKm); 
//Aufruf der Kfz-Methode
       meldung = "km-Zahl des Autos "+amtlKennzeichen+
                       
" auf "+neueKm+" verändert";
     }    
     
return (meldung);
  }
  
  
public String löschen (String altesKennzeichen)
  
//Löscht Auto mit dem angegebenen Kennzeichen aus dem Fuhrpark
  {      
     String meldung = 
"Auto "+altesKennzeichen
                         +
" nicht gefunden -- nicht gelöscht";
     //Finden des Index i vom Auto mit der gesuchten Nummer
     int i = anzahlDerAutos - 1; //von hinten beginnen
     while ((i>=0)&&(! fuhrpark[i].nummer().equals(altesKennzeichen)))
     {          
//equals statt == , da versch. Objekte mit gleichem Inhalt
       i = i-1;  
     }  
     
//Auto löschen durch Vorziehen des Fuhrpark-Restes
     if (i>=0) //Auto gefunden -- sonst ist i = -1
     {
       anzahlDerAutos--; 
//Löschen verkleinert Anzahl
       for (int j=i; j < anzahlDerAutos; j++)
       {
         fuhrpark[j].kopiereVon (fuhrpark[j+1]); 
//nutzt Kfz-Methode
       }
       meldung = 
"Auto "+altesKennzeichen+" wurde gelöscht!";  
     } 
     
return (meldung); 
  }
  
  
public String listeAutosVon (String produzent)
  
//Erzeugt Text mit den Daten der Autos vom genannten Hersteller
  {
    
String ausgabe = "";
    
for (int i=0; i<anzahlDerAutos; i++)
    {  
      
if (fuhrpark[i].hersteller().equals (produzent))
      { 
        ausgabe = ausgabe+(i+1)+
".) "+fuhrpark[i].nennen()+"\n"
      }   
    }                                
//nutzt Kfz-Methode  
    return (ausgabe); 
  }  

  
  
private void tausche (int i, int j)
  
// vertauscht innerhalb des Fuhrparks die beiden Autos 
  // an den Positionen i und j. Wird beim Sortieren benötigt.
  {
    Kfz drittesAuto = 
new Kfz();  //Zwischenspeicher    
    drittesAuto.kopiereVon (fuhrpark[i]); 
    fuhrpark[i].kopiereVon (fuhrpark[j]);
    fuhrpark[j].kopiereVon (drittesAuto);
  }  
    
  
public void minSortNr () // MinSort nach Autonummer
  // Sortieren durch Auswahl des jeweils kleinsten Elements im Rest
  // und Tausch dieses Elements nach vorne. Nach dem 0. Durchgang steht
  // also das kleinste Element ganz links auf Platz 0, beim nächsten Durchgang
  // kommt das nächtkleinere Element auf Platz 1 usw., so dass die Sortierung
  // von links nach rechts wächst
  {
    
int minStelle, durchgang, stelle;
    
    
for (durchgang=0; durchgang<anzahlDerAutos; durchgang++)
    {
      minStelle = durchgang; 
// vorderstes El. im unsortierten Teil zum Vergleich
      for (stelle=durchgang+1; stelle<anzahlDerAutos; stelle++)
      {
        
if (fuhrpark[stelle].nummer().compareTo(fuhrpark[minStelle].nummer())<0)
        {
           
// wird ein kleineres Element gefunden, so wird dessen Index gemerkt
           minStelle = stelle; 
        }    
      }
      
// das gefundene kleinste Element wird nach vorne (auf den Platz mit
      // dem Index durchgang) getauscht, sofern es nicht schon dort steht:
      if (minStelle > durchgang)
      {
        tausche (durchgang, minStelle);
      }  
    }
  }

  
  
public void minSortKm () // MinSort nach km-Stand
  // Sortieren durch Auswahl des jeweils kleinsten Elements im Rest
  // und Tausch dieses Elements nach vorne. Nach dem 0. Durchgang steht
  // also das kleinste Element ganz links auf Platz 0, beim nächsten Durchgang
  // kommt das nächtkleinere Element auf Platz 1 usw., so dass die Sortierung
  // von links nach rechts wächst
  {
    
int minStelle, durchgang, stelle;
    
    
for (durchgang=0; durchgang<anzahlDerAutos; durchgang++)
    {
      minStelle = durchgang; 
// vorderstes El. im unsortierten Teil zum Vergleich
      for (stelle=durchgang+1; stelle<anzahlDerAutos; stelle++)
      {
        
if (fuhrpark[stelle].kmZahl() < fuhrpark[minStelle].kmZahl())
        {
           
// wird ein kleineres Element gefunden, so wird dessen Index gemerkt
           minStelle = stelle; 
        }    
      }
      
// das gefundene kleinste Element wird nach vorne (auf den Platz mit
      // dem Index durchgang) getauscht, sofern es nicht schon dort steht:
      if (minStelle > durchgang)
      {
       tausche (durchgang, minStelle);
      }  
    }
  }

  
  
public String aufDisk (String dateiName)
  
//schreibt alle Autos des Fuhrparks unter dateiName auf Disk
  {
    ObjectOutputStream oos; 
    String meldung = 
"";
    
try 
    {
      oos = 
new ObjectOutputStream(new FileOutputStream (dateiName));  
        
//öffnet die Datei zum Schreiben. Evtl. alte Datei wird überschrieben.
      for (int i=0; i<anzahlDerAutos; i++) //geht ganzen Fuhrpark durch
      {               
        oos.writeObject (fuhrpark[i]); 
//schreibt jeweils ein Auto vom Typ Kfz
      }
      oos.close(); 
//schließt die Datei
      meldung = ""+anzahlDerAutos+" Auto(s) in '"+dateiName+"' gespeichert.\n";       
    }
    
catch (IOException ex)
    {
      meldung = 
"Fehler beim Speichern: "+ex+"\n";
    }
    
return (meldung); //gibt Erfolgs- oder Fehlermeldung zurück
  }

  
public String vonDisk (String dateiName)
  
//ersetzt den bisherigen Fuhrpark durch die Autos von Disk
  {
    ObjectInputStream ois;     
    String meldung = 
"";
    
int i = 0; //hier deklariert, damit noch nach for-Schleife verfügbar
    try 
    {
      ois = 
new ObjectInputStream(new FileInputStream(dateiName));
        
//öffnet Datei zum Lesen (Fehler, falls nicht gefunden)
      try 
      { 
        for (i=0; i<25; i++) //Schleife wird durch EOF abgebrochen!
        {    
          fuhrpark[i] = (Kfz) ois.readObject (); 
//liest ein Auto          
        } 
        
//Diese Stelle wird nie erreicht: Durch EOF aus Schleife in catch
      }  
      catch (EOFException eex) //Fehler entsteht durch Dateiende
      {
         ois.close();          
//Datei schließen        
         anzahlDerAutos = i;   //anzahlDerAutos = gelesene Zahl
           //letztes gelesenes Auto hat Wert null => nicht berücksichtigen,
           //also nicht anzahlDerAutos = i+1;
         meldung = ""+anzahlDerAutos+" Auto(s) aus Datei '"+dateiName
                        +
"' gelesen.";
      } 
    }  
    
catch (Exception ex) // nicht nur IO-, auch ClassNotFound-Exception!
    {
      meldung = 
"Fehler beim Lesen: "+ex+"\n";
    }
    
return (meldung);    
  }
 
 
 public String listeAlle()
  
//Erzeugt Text mit den Daten aller Fahrzeuge: 1 Zeile pro Auto
  {
    String ausgabe = 
"";
    
for (int i=0; i<anzahlDerAutos; i++)
    {  
      ausgabe = ausgabe+(i+1)+
".) "+fuhrpark[i].nennen()+"\n"
    }                                
//nutzt Kfz-Methode  
    return (ausgabe); 
  }         
 

   



zum Seitenanfang / zum Seitenende


//Kfz-Verwaltung, Datei 3/4
//Java JDK 1.1.18 -- Krell 21.2.2002/5.3.02
import java.awt.*;
import java.awt.event.*;
import java.io.*;

//Benutzer-Oberfläche der Kfz-Verwaltung, die ihrerseits ein Objekt
//namens alleAutos der Klasse KfzFuhrpark anlegt und verwaltet

public class KfzGUI extends Frame  
{  
  KfzFuhrpark alleAutos   = 
new KfzFuhrpark();  //Def. und Erzeugen

  TextField tfKennzeichen = 
new TextField("",10);
  TextField tfHersteller  = 
new TextField("",20);
  TextField tfModell      = 
new TextField("",17);
  TextField tfBaujahr     = 
new TextField("",6);
  TextField tfKmStand     = 
new TextField("",8);
  TextField tfDateiname   = 
new TextField("KfzDatei.Dat",15);
  Button    btNeuesAuto   = 
new Button("Auto neu aufnehmen");
  Button    btNeueKm      = 
new Button("km-Stand eines vorhandenen Autos ändern (*)");
  Button    btLöschen     = 
new Button("Auto löschen (^)");
  Button    btHersteller  = new Button("Alle Autos eines Herstellers (%) finden");
  Button    btSortNr      = 
new Button("Autos nach Nummer sortieren");
  
Button    btSortKm      = new Button("Autos nach km sortieren");
  Button    btSpeichern   = new Button("Fuhrpark speichern");
  Button    btLaden       = 
new Button("Fuhrpark laden");
  Button    btZeigen      = new Button("Fuhrpark zeigen");
  TextArea  taAusgabe     = new TextArea(9,75);
  
  
public void richteFensterEin() // Fenster initalisieren und beschreiben
  {
    
//WindowsListener hinzufügen, damit Schließknopf funktioniert
    addWindowListener (    
      
new WindowAdapter ()
      {
        
public void windowClosing (WindowEvent ereignis)
        {                
//ersetzt bisher leere Methode 
          setVisible (false);
          dispose();
          System.exit(0);
        }
      }
    ); 
// runde Klammer vom Windowlistener geschlossen;  
  }  
  
  
public void richteKnöpfeEin()
  {
  
btNeuesAuto.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        
taAusgabe.setText ("Bitte alle Felder ausfüllen -- Ganze Zahlen bei
                               Baujahr und km-Stand!"
);
        alleAutos.neuesAuto (tfKennzeichen.getText(), tfHersteller.getText(),
          tfModell.getText(), Integer.parseInt(tfBaujahr.getText()),
          Integer.parseInt(tfKmStand.getText())); 
//Auto aufnehmen
        taAusgabe.setText ("Auto "+tfKennzeichen.getText()+" aufgenommen!\n");
        tfKennzeichen.setText(
""); //und Eingabefelder löschen
        tfHersteller.setText("");
        tfModell.setText(
"");
        tfBaujahr.setText(
"");
        tfKmStand.setText(
"");
      }
    }); 
//runde Klammer (von btNeuesAuto.addActionListener)    
  
  
btNeueKm.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        taAusgabe.setText (
"Bitte Kennzeichen eingeben und eine ganze Zahl für
                               den (neuen) km-Stand!"
);
        taAusgabe.setText(alleAutos.ändereKmStand (tfKennzeichen.getText(), 
          Integer.parseInt(tfKmStand.getText()))
); //km ändern, Erfolg melden
        tfKennzeichen.setText(""); //und Eingabefelder löschen
        tfKmStand.setText("");
      }
    }); 
//runde Klammer (von btNeueKm.addActionListener)   
  
  
btLöschen.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        taAusgabe.setText(alleAutos.löschen (tfKennzeichen.getText())); 
           
//Auto löschen, Erfolg melden
        tfKennzeichen.setText(""); //und Eingabefeld löschen
      }  
    }); //runde Klammer (von btLöschen.addActionListener)  
         
  
btHersteller.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        taAusgabe.setText(alleAutos.listeAutosVon (tfHersteller.getText())); 
        tfHersteller.setText(
""); //und Eingabefeld löschen
      }  
    }); //runde Klammer (von btHersteller.addActionListener)  
         
  
btSortNr.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        alleAutos.minSortNr (); 
        taAusgabe.setText(
"Autos wurden lexikografisch nach Kennzeichen
                              sortiert"
);
      }  
    }); //runde Klammer (von btSortNr.addActionListener)  

 
 btSortKm.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        alleAutos.minSortKm (); 
        taAusgabe.setText(
"Autos wurden nach dem km-Stand sortiert");
      }  
    }); //runde Klammer (von btSortKm.addActionListener)

  
btSpeichern.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {                    
//alle Autos auf Disk speichern
        taAusgabe.setText( alleAutos.aufDisk (tfDateiname.getText()));
      }
    }); 
//runde Klammer (von btSpeichern.addActionListener)      
    
  
btLaden.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {                     
//alle Autos von Disk lesen
        taAusgabe.setText( alleAutos.vonDisk (tfDateiname.getText()));
      }
    }); 
//runde Klammer (von btLaden.addActionListener) 
    
  
btZeigen.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {                    
//Liste aller Autos anzeigen
        taAusgabe.setText( alleAutos.listeAlle() );
      }
    }); 
//runde Klammer (von btZeigen.addActionListener)   
  } //Ende von richteKnöpfeEin


  
public void führeAus ()
  { 
    setTitle(
"Fuhrpark-Verwaltung"); // Fenster-Titel
    setSize (600,350); // Fenstergröße (Breite und Höhe in Pixeln)
    setLayout (new FlowLayout()); 
    richteFensterEin();        
    richteKnöpfeEin();
    add (
new Label("Amtliches Kennzeichen (*,^):"));
    add (tfKennzeichen);
    add (
new Label("Fahrzeughersteller (%):"));
    add (tfHersteller);
    add (
new Label("Modell:")); 
    add (tfModell);
    add (
new Label("Baujahr:"));
    add (tfBaujahr);
    add (
new Label("Aktueller Stand (*):"));
    add (tfKmStand);
    add (
new Label("km."));
    add (btNeuesAuto);
    add (btNeueKm);
    add (btLöschen);
    add (btHersteller);
    add (btSortNr);
    add (btSortKm);
    add (
new Label("Dateiname:"));
    add (tfDateiname);
    add (btSpeichern);
    add (btLaden);
    add (
new Label(" "));
    add (btZeigen);
    add (taAusgabe);     
    setVisible(
true);               
  }   
}




zum Seitenanfang / zum Seitenende


//Kfz-Verwaltung, Datei 4/4
//Java JDK 1.1.18 -- Krell 21.2.2002
//Definiert, erzeugt und startet ein Objekt der Klasse KfzGUI

public class KfzStart extends java.applet.Applet 
{
  
//Start als selbständige Application
  public static void main (String[] s) 
  {
    KfzGUI autoVerw = 
new KfzGUI();
    autoVerw.führeAus();
  }
  
  
//Start als Applet aus dem Web-Browser
  public void init()
  {
    KfzGUI autoVerw = 
new KfzGUI();
    autoVerw.führeAus();
  }     

}        




zum Seitenanfang / zum Seitenende



Verbesserungsvorschlag 2003:
vergleicheMit mit Auswahl eines Sortierkriteriums

Gerade nach den anfängliche Ausführungen über vernünftige Klasseneinteilungen (s.o.) ist es eigentlich nicht einzusehen, warum oben in der Klasse KfzFuhrpark zwei Sortier-Methoden implementiert wurden - die Sortierung nach dem Kfz-Kennzeichen bzw. die Sortierung nach dem Kilometerstand. Schließlich handelt es sich bei Nummer und km-Stand um Eigenschaften des Autos, die in der Klasse Kfz stehen und nicht in KFzFuhrpark. Außerdem ist der Algorithmus beider Sortierverfahren identisch - nur eine Zeile mit dem Vergleich unterscheidet sich. Es erscheint daher sinnvoll, eine Methode vergleicheMit innerhalb der Klasse Kfz anzusiedeln, die dann aus der Klasse KfzFuhrpark in einem einzigen, allgemeinen Sortierverfahren benutzt werden kann (der Name vergleicheMit lag nahe, weil es für Zeichenketten [Strings] in Java bereits eine mitgelieferte Methode compareTo gibt, die ähnlich zu nutzen ist). vergleicheMit gehört auch deshalb in die Klasse Kfz, weil schon ein einzelnes Fahrzeug mit einem anderen verglichen werden kann. Es bedarf dazu nicht der Reihung, die typisch für den KfzFuhrpark ist.

Die Methode vergleicheMit müsste nun einen Parameter erhalten, mit dem man das Sortier- bzw. Vergleichskriterium wählen kann - ob also zwei Autos (bzw. das aktuelle Objekt mit einem weiteren, als Parameter angegebenen Auto) hinsichtlich der Nummer oder des km-Standes oder vielleicht noch bezüglich einer anderen Eigenschaft des Fahrzeugs/der Fahrzeuge verglichen werden sollen. Da der Vergleich zu einer Reihenfolge führen muss, liegt es nahe, wie bei compareTo ein numerisches Ergebnis zurück zu geben: eine negative Zahl bedeutet, dass das aktuelle Auto bezüglich des Kriteriums vor dem übergeben Auto stehen muss. Das Ergebnis 0 bedeutet Gleichrangigkeit, und bei positivem Ergebnis gehört das aktuelle Auto hinter das Parameter-Auto bei einem Ranking nach dem ausgewählten Kriterium.

Die Kriteriumsauswahl kann beliebig kompliziert erfolgen: Am saubersten wäre wohl die Vereinbarung eines Interfaces, das Konstanten zur Auswahl verschiedener Kfz-Eigenschaften enthält. Die Klassen Kfz und KfzFuhrpark und auch die Oberfläche könnten dann dieses Interface implementieren.

Für einen ersten Zugang reicht aber evtl. auch die Auswahl über einen Kennbuchstaben, z.B. 'n' = Nummer und 'k' = km-Stand. Damit würde dann die Kfz-Datei oben um folgende Methode ergänzt:

      public int vergleicheMit (Kfz anderesAuto, char kriterium)
    
//Vergleicht Autos bzgl. der ausgewählten Eigenschaft
    {       
      switch (kriterium)
      {
        case 'n' : return (
kennzeichen.compareTo (anderesAuto.kennzeichen));
        case 'k' : return (kmStand - anderesAuto.kmStand);
      }

    } 

Ein break nach dem case ist wegen des returns nicht nötig (und auch nicht mehr erlaubt).

Innerhalb der Klasse KfzFuhrpark gäbe es dann nur noch eine einzige Sortiermethode. Die veränderten Teile sind kursiv:

  public void minSort (char kriterium// MinSort nach angegebenem Kriterium
  // Sortieren durch Auswahl des jeweils kleinsten Elements im Rest
  // und Tausch dieses Elements nach vorne. Nach dem 0. Durchgang steht
  // also das kleinste Element ganz links auf Platz 0, beim nächsten Durchgang
  // kommt das nächtkleinere Element auf Platz 1 usw., so dass die Sortierung
  // von links nach rechts wächst
  {
    
int minStelle, durchgang, stelle;
    
    
for (durchgang=0; durchgang<anzahlDerAutos; durchgang++)
    {
      minStelle = durchgang; 
// vorderstes El. im unsortierten Teil zum Vergleich
      for (stelle=durchgang+1; stelle<anzahlDerAutos; stelle++)
      {
        
if (fuhrpark[stelle].vergleicheMit(fuhrpark[minStelle], kriterium)<0)
        {
           
// wird ein kleineres Element gefunden, so wird dessen Index gemerkt
           minStelle = stelle; 
        }    
      }
      
// das gefundene kleinste Element wird nach vorne (auf den Platz mit
      // dem Index durchgang) getauscht, sofern es nicht schon dort steht:
      if (minStelle > durchgang)
      {
        tausche (durchgang, minStelle);
      }  
    }
  }

  

Und in der Oberfläche KfzGUI müssten dann die beiden Aufrufe aus den Knopf-Methoden abgeändert werden:

  btSortNr.addActionListener (
    new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        alleAutos.
minSort ('n')
        taAusgabe.setText(
"Autos wurden lexikografisch nach Kennzeichen
                              sortiert"
);
      }  
    }); //runde Klammer (von btSortNr.addActionListener)  

 
 btSortKm.addActionListener (
    
new ActionListener ()
    {
      
public void actionPerformed (ActionEvent e)
      {
        alleAutos.
minSort ('k')
        taAusgabe.setText(
"Autos wurden nach dem km-Stand sortiert");
      }  
    }); //runde Klammer (von btSortKm.addActionListener)

So erscheint mir das Programm jetzt viel eleganter, zumal sich (durch weitere case-Fälle) leicht weitere Kriterien beim Kfz hinzufügen lassen, ohne den KfzFuhrpark zu beeinflussen. vergleicheMit lässt sich selbstverständlich auch mit jeder Suche bestens verwenden!


zurück zur Informatik-Hauptseite

(Die anderen „Informatik mit Java"-Seiten werden entweder mit dem Menü hier am Seitenanfang oder
am besten auch auf der Informatik-Hauptseite ausgewählt)


zum Anfang dieser Seite
Willkommen/Übersicht  -  Was ist neu?  -  Software  -  Mathematik  -  Physik  -  Informatik  -   Schule: Lessing-Gymnasium und -Berufskolleg  -  Fotovoltaik  -  & mehr  -  Kontakt: e-Mail,  News-Abo, Gästebuch, Impressum  -  Grußkarten, site map, Download und Suche

Diese Seite ist Teil des Webangebots http://www.r-krell.de. Sie können diese Seite per e-Mail weiter empfehlen (tell a friend).