2010-03-06 18 views
5

Ich arbeite an einem Transliterationswerkzeug. Ich habe zwei Module lexer und Übersetzer. Lexer generiert Token aus dem Eingabetext. Abhängig von der gewählten Sprache muss ich die entsprechende Übersetzungsroutine aufrufen.Ausführen von Funktionen abhängig vom Wert einer Variablen - C++

Ich habe ein paar Ideen, um dies zu tun. Die erste besteht darin, eine Basisklasse namens base_translator zu erstellen und eine virtuelle Methode (translate()) bereitzustellen, die jeder Übersetzer überschreiben muss. Erstellen Sie jetzt eine Factory translator_factory und rufen Sie create() mit dem Sprachennamen auf. Diese Fabrik wird die entsprechende Instanz zurückgeben.

Aber das scheint über Engineering zu sein. Also habe ich einen anderen Ansatz gefunden, bei dem ich eine Struktur wie die folgende habe.

struct translator 
{ 
    const char* name; 
    void (*fp)(); 
}; 

Welche nur einen Sprachnamen und einen Funktionszeiger behält, der es verarbeiten kann. Verwendung wird sein,

static translator translators[] = { 
    {"first", first}, 
    {"second", second} 
}; 
const char* language = /* */; 
for(int i = 0; i < 2; i++) { 
    translator *t = translators + i; 
    if(strcmp(t->name, language) == 0) { 
     t->fp(); 
     break; 
    } 
} 

Dieser Ansatz ist sehr einfach und leicht zu pflegen. Aber ich frage mich, ist dies der beste Ansatz für das Problem? Hast du irgendwelche Vorschläge, um das besser zu machen?

Jede Hilfe wäre großartig.

+0

Ihr zweiter Ansatz emuliert lediglich den C++ - Laufzeitpolymorphismus (virtuelle Funktionen) im C-Stil. Es hat keine Vorteile gegenüber der integrierten Unterstützung für OOP in C++. –

Antwort

3

Ihr zweiter Ansatz sieht für zwei Dinge einfacher aus (naja, für mich ist es nicht ...), aber auf lange Sicht ist er fehleranfälliger und schwieriger zu pflegen. Wenn Sie eine neue Sprache hinzufügen, müssen Sie den Code an mindestens zwei Stellen berühren. (Und vertraue mir: auch wenn dir das momentan unwahrscheinlich erscheint, wird es fast zwangsläufig passieren ...) Wenn du vergisst, deine Loop-Grenze zu aktualisieren, hast du einen stillen Bug in deinem Code. Darüber hinaus ist diese Implementierung viel langsamer als eine polymorphe: Sie müssen vor jedem Aufruf über das Array iterieren und Zeichenfolgen vergleichen (im Gegensatz zum Nachschlagen eines Zeigers in der vtable).

Ich würde auf jeden Fall eine Fabrik verwenden. Abgesehen von den oben genannten Vorteilen ist es ein bekanntes Entwurfsmuster, das es leichter verständlich macht. So werden Leute, die nach Ihnen kommen, um Ihren Code zu pflegen, Sie nicht so sehr verfluchen ;-)

Aktualisierung: Eine Fabrik kann einen Funktionszeiger auch zurückbringen. In diesem Fall würde ich immer noch functors intern verwenden, da dies vollwertige Klassen mit allen oben aufgeführten Vorteilen sind. Und noch eines, nicht explizit erwähnt: Sie (als reale Objekte) können den Zustand speichern, was einfache Funktionen nicht können. Das kann später einen großen Unterschied machen und dein Design sehr vereinfachen. Sobald Sie die Factory-Schnittstelle installiert haben, können Sie natürlich Ihre interne Darstellung der Produkte von einfachen Funktionen zu Funktoren (und zurück) ändern.

+0

Danke. Fabrik macht mehr Sinn. Wie wäre es, wenn factor den Funktionszeiger und nicht eine polymorphe Instanz zurückgibt? –

+0

@Appu Siehe mein Update. –

+0

Vielen Dank für die Hilfe. Ich schätze es sehr. –

5

Dies ist normalerweise ein glücklicher Anwendungsfall für abstrakte Klassen und virtuelle Funktionen. Ich verstehe nicht, warum Sie es als "over-engineering" ... o_O

Der Punkt ist, einen Vertrag zu definieren, so dass Ihr Code leicht erweiterbar ist, und der "Hauptcode" hat nicht sich um die tatsächlichen Implementierungsdetails kümmern.

2

Jede Lösung gilt für das Problem, wie Sie es angegeben haben. Die Fabrik ist wahrscheinlich schöner, wenn der Problemraum überhaupt wächst. Wenn Sie beispielsweise in Zukunft eine weitere sprachabhängige Klasse oder Funktion benötigen, können Sie die Factory erweitern, um auch diese zurückzugeben. Die Tabelle der Funktionszeiger würde mehr Änderungen erfordern, um so etwas zu handhaben. Ich würde mit einer Fabrik gehen. Problemdomänen wachsen immer.

Verwandte Themen