006
25.07.2007, 13:35 Uhr
virtual
Sexiest Bit alive (Operator)
|
Ja, ist bereits eine Factory, allerdings eben eine statische.
Was mir vorschwebt ist eine dynamische, aber ob der Aufwand lohnt, hängt vom konkreten Anwendungsfall ab.
Hier eine Skizze:
1. Alle Typen, welche "Factory-enabled" sein sollen (also über die factory erstellbar sein sollen), wandern in DLLs. Dabei kann man je nach gewünschter granularität pro typ eine eigene DLL machen oder aber auch mehrere zusammenfassen.
2. Zu jeder DLL werden nun zwei Funktionen mit C Linkage definiert:
C++: |
extern "C" const char** get_known_types(); extern "C" void* instantiate(const char* type_name, parameters);
|
also zB:
C++: |
static const char* types[] = { "A-Typ", "B-Typ" }; extern "C" const char** get_known_types() { return types; }
extern "C" void* instantiate(const char* type_name, parameters) { if (!strcmp(type_name, "A-Typ") { return new ATyp(parameters); } else (!strcmp(type_name, "B-Typ") { return new BTyp(parameters); } else { return NULL; } }
|
Sicherlich: auch hier gibt es sowas ähnliches wie ein "switch", aber die Fallunterscheidung braucht wirklich nur die Typen zu können, die unmittelbar in diesem Modul auch definiert sind. bei dem statischen Ansatz würden alle Typen in der fallunterscheidung zu berücksichtigen sein, was nicht grade flexibel oder Wartungsfreundlich ist.
Die eigentliche faktory kann nun entweder mit einer Konfigurationsdatei gefüttert werden oder eben alle DLLs aus einem bestimmten Verzeichnis dynamisch einbinden. Wie ist jetzt mal egal, aber sie funktioniert im wesentlichen wie folgt:
1. Alle DLLs mit factory-enabled Typen ermitteln. (zB: Liste der DLLs in Textfile/XML bereitstellen, oder alle DLLs in einem bestimmten Verzeichnis durchkämmen)
2. Alle DLLs nun dynamisch dazu laden (dlopen unter Unix, LoadLibrary oder so unter Windows)
3. Für jede DLL die einstiegspunkte instantiate merken und get_known_types aufrufen. So kann eine Liste von bekannten Typen aufgebaut werden, zB für jeden Typen ein Eintrag der form:
C++: |
struct type_entry { native_dll_handle* dll; // Handle zur DLL native_funtion_handle* instantiator; // Funktionseintritt für "instantiate" methode const char* name; // Typ name }
|
4. Alles was die Factory sonst noch tun muß, ist dann den zu einem namen passenden type_entry ermitteln und dessen instantiator aufrufen.
Den ansatz kann man auch ohne DLLs machen. Voraussetzung ist, daß das Betriebssystem es erlaubt in einem normalen Executable eintrittspunkte zu exportieren. Dann reduziert sich der Aufwand natürlich ein wenig. -- Gruß, virtual Quote of the Month Ich eß' nur was ein Gesicht hat (Creme 21) |