Mal eine Frage vorweg:
Wozu hast du
alle Methoden als
virtual
deklariert?
Als
virtual
deklariert man Methoden, wo man bei der Entwicklung schon absehen kann, dass diese Methoden wohl meistens überschrieben werden.
Als
virtual abstract
deklariert man Methoden, die überschrieben werden
müssen.
Alle anderen Methoden können auch überschrieben werden, allerdings war das eigentlich nicht im Sinne des Entwicklers (was alles und nichts bedeuten muss).
Zum Thema:
Also ich würde das Speichern nicht in die Liste reinpacken (allerdings würde ich in die Liste auch nicht das Auswürfeln der Vokabeln reinpacken).
Delphi-Quellcode:
type
// Container für die Vokabeln
TListe =
class
public
procedure Clear;
function Add( AItem : TVokabel ) : Integer;
property Count : Integer
read GetCount;
property Items[
const Index : Integer] : TVokabel
read GetItem;
end;
// Der Vokabeltrainer (braucht aber einen Container)
TTrainer =
class
private
FListe : TListe;
procedure SetListe(
const Value : TListe );
public
procedure Reset;
virtual;
abstract;
property Liste : TListe
read FListe
write SetListe;
end;
// Das Speichermodul für den Container
TStorage =
class
private
FFilename :
string;
protected
procedure DoSave( AListe : TListe );
virtual;
abstract;
procedure DoLoad( AListe : TListe );
virtual;
abstract;
public
constructor Create(
const AFilename :
string );
procedure Save( AList : TListe );
procedure Load( AList : TListe );
property Filename :
string read FFilename;
end;
TStorageClass =
class of TStorage;
procedure TTrainer.SetListe(
const Value : TListe );
begin
if Value = FListe
then
Exit;
FListe := Value;
Reset;
end;
constrcutor TStorage.Create(
const AFilename :
string );
begin
inherited;
FFilename := AFilename;
end;
procedure TStorage.Save( AListe : TListe );
begin
if not Assigned( AListe )
then
raise Exception.Create( '
Keine Listen-Instanz übergeben!' );
DoSave( AListe );
end;
procedure TStorage.Load( AListe : TListe );
begin
if not Assigned( AListe )
then
raise Exception.Create( '
Keine Listen-Instanz übergeben!' );
DoLoad( AListe );
end;
Von der Klasse
TStorage
leitet man nun die konkreten Klassen (z.B.
TIniStorage
,
TPlainTextStorage
,
TMyBaseStorage
, ...) ab.
Um nun die Liste in eine Datei zu speichern macht man folgendes:
Delphi-Quellcode:
procedure SaveListe( AListe : TListe;
const AFilename :
string );
var
LStorage : TStorage;
// kein konkreter Typ!!!
LStorageClass : TStorageClass;
begin
case IndexText( ExtractFileExt( AFilename ), ['
.txt','
.ini','
.xml','
.db'] )
of
0 :
// PlainText-Datei
LStorageClass := TPlainTextStorage;
1 :
// Ini-Datei
LStorageClass := TIniStorage;
2, 3 :
// MyBase-Datei
LStorageClass := TMyBaseStorage;
else
raise Exception.CreateFmt( '
Unbekannte Dateiendung "%s"', [ExtractFileExt( AFilename )] );
end;
// Jetzt kommt das Speichern
LStorage := LStorageClass.Create( AFileName );
try
LStorage.Save( AListe );
finally
LStorage.Free;
end;
end;
Am Anfang wird es wohl durchaus reichen
eine einfache Storage-Klasse zu entwerfen ... aber man sollte auch verstehen, warum eine Trennung der Klassen besser ist