Autor Beitrag
Flamefire
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1207
Erhaltene Danke: 30

Win 10
Delphi 2009 Pro, C++ (Visual Studio)
BeitragVerfasst: Sa 29.07.17 12:41 
Ich stelle gerade eine Bibliothek um, die Dateien eines Spiels (Siedler 2) liest und schreibt. Allgemein habe ich hier Datei-Objekte mit einzelnen Inhalten (z.B. ein Bild, Sound, ...) oder Ordner bzw. in mehrere Dateien in einer (Archiv).

Die Grundobjekte sind hier die Klassen ArchivInfo und ArchivItem, wobei ein ArchivInfo mehrere ArchivItems enthalten kann, die wiederum (C++ Mehrfachvererbung) ArchivInfos sein können. Das macht das ganze sehr flexibel, da ich so ein Ordner oder ein Orner von Ordnern oder einzelne Dateien einlesen kann.

Aktuell existiert pro Dateiformat eine eigene Klasse. Außerdem existieren noch Methoden, die einzelne Dateitypen (bmp, ogg, ...) lesen können und sich teils der Klassen-methoden bedienen um die zu lesen oder zu schreiben. Ein Allokator (kann vom Nutzer ausgetauscht werden) kann abhängig von einem Enum-Wert eine bestimmte Klasse erzeugen oder Klonen.
Dabei habe ich 3 Probleme festgestellt:
1. Eine bitmap kann als raw (bmp), komprimiert (RLE), oder getaggt (Schatten) abgespeichert werden. Im Prinzip ist es aber alles nur eine Bitmap. Nur die Lese/Schreibmethoden sind anders, um die unkomprimierte Bitmap von oder auf die Platte zu bekommen. Hier denke ich, dass es sinnvoll ist, nur eine Klasse Bitmap zu haben, die dann von Lese/Schreibmethoden abhängig vom Format (Enum-Wert in ArchivItem) befüllt wird.
2. In einer Datei läuft alles zusammen nach dem Schema: If Endung="bmp"->Lade Bitmap, else if Endung="ogg"->Lade Sound usw.
Schöner wäre das allgemein zu machen. Da habe ich daran gedacht, ein Singleton zu erstellen, bei dem sich jede Lade/Schreib methode samt des Dateityps registriert. Dann weiß das Singleton nix mehr von den Methoden und leitet einfach weiter. Außerdem kann der Benutzer noch eigene Methoden erstellen um weitere Dateitypen zu unterstützen.

Und letztens ist noch das Problem, dass im Programm (Nutzer der Bibliothek) eigene abgeleitete Klassen existieren, um z.B. OGL Draw-Methoden hinzuzufügen. Dabei wird teils virtuelle Vererbung eingesetzt was wirklich hässlich ist aber im aktuellen Design nicht anders geht.
Darum die Idee mit dem Singleton und dem registrieren. Eigene Klassen könnte man dann statt Vererbung mit "enthält" lösen: Laden einer Grafik erzeugt im Nutzerprogramm eine OGL Klasse, der Standard-Loader wird aufgerufen um die Grafik zu laden und die wird in die OGL Klasse gegeben. Dann wird die OGL Klasse (Erbe von ArchivItem) zurückgegeben.

Frage: Wie kann ich das Registrieren sinnvoll lösen? In der statischen Initialisierung ist die Reihenfolge nicht garantiert. Ich weiß also nicht, ob die Bibliothekstypen vor den Nutzertypen registriert werden womit das (Rufe Standard-Loader auf) schwierig wird. Oder ich müsste 2 Listen haben: Erst nutzerliste probieren, dann default Liste mit Option nur die Defaultliste zu nehmen.

Oder ist das insgesamt keine gute Design Idee?
Wie machen andere das bzw. hat jemand dazu noch gute Ideen? Bin für alles offen.

Wenn jemand Interesse hat, die Bibliothek ist hier: github.com/Return-To-The-Roots/libsiedler2
Blup
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 163
Erhaltene Danke: 41



BeitragVerfasst: Mi 02.08.17 17:11 
Ich würde jeder Loader-Klasse jeweils Dateiname und Binärdaten bereitstellen und diese Fragen ob sie sich dafür zuständig findet. So könnte man z.B. für jeden BMP-Typ eine eigene Klasse registrieren. Die Loader-Klasse muss natürich auch die Information liefern, welchen Datentyp (Sound, Bitmap, ..) sie bereitstellt.
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 10

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Mi 02.08.17 20:49 
Beim Filemanager wird die Dateiendung + Loaderklasse registriert. Dieser sortiert alle nach zuerst Nutzer und dann Standard Loader. Der Manager hat eine Funktion LoadFile der die 1. passende Klasse nimmt und eine Instanz anlegt. Im Grunde leiten dann alle Loader von einer abstrakten Klasse ab. Die Dateiendung kann auch als class function Teil der Loader-Klasse sein.

_________________
wer andern eine grube gräbt hat ein grubengrabgerät
- oder einfach zu viel zeit