2010-03-06 7 views
5

Estoy trabajando en una herramienta de transliteración. Tengo dos módulos, lexer y traductor. Lexer genera tokens fuera del texto de entrada. Dependiendo del idioma actual elegido, debo llamar a la rutina de traducción adecuada.Ejecutando funciones dependiendo del valor de una variable - C++

He tenido algunas ideas para hacer esto. El primero es crear una clase base llamada base_translator y proporcionar el método virtual (translate()) que todos los traductores tienen que anular. Ahora cree una fábrica translator_factory y llame al create() con el nombre del idioma. Esta fábrica devolverá la instancia apropiada.

Pero esto parece ser una sobreingeniería. Así que se me ocurrió otro enfoque en el que tengo una estructura como la siguiente.

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

Que solo conserva el nombre de un idioma y un puntero a la función que puede procesarlo. El uso será,

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; 
    } 
} 

Este enfoque es muy simple y fácil de mantener. Pero me pregunto, ¿este es el mejor enfoque para el problema? ¿Tienes alguna sugerencia para mejorar esto?

Cualquier ayuda sería genial.

+0

Su segundo enfoque simplemente emula el polimorfismo en tiempo de ejecución de C++ (funciones virtuales) en estilo C. No tiene ninguna ventaja sobre el soporte integrado para OOP en C++. –

Respuesta

3

Su segundo enfoque puede parecerle más simple para dos elementos (bueno para mí no ...), pero es más propenso a errores y más difícil de mantener a largo plazo. Cada vez que agrega un nuevo idioma, debe tocar el código en al menos dos lugares. (Y créanme: incluso si esto les parece poco probable en este momento, es casi inevitable que suceda ...) Si olvida actualizar su límite de bucle, tiene un error silencioso en su código. Además, esta implementación es mucho más lenta que una polimórfica: necesita iterar sobre la matriz y comparar cadenas de caracteres antes de cada llamada (en lugar de buscar un puntero en la tabla).

Definitivamente usaría una fábrica. Además de los beneficios anteriores, es un patrón de diseño bien conocido que lo hace más fácil de entender. Por lo tanto, las personas que lo siguen para mantener su código no lo maldecirán ;-)

Actualización: Una fábrica también puede devolver un puntero a la función. En este caso, seguiría usando functors internamente, porque estas son clases completas con todos los beneficios enumerados anteriormente. Y uno más, no mencionado explícitamente: ellos (como objetos reales) pueden almacenar estados, lo que las funciones simples no pueden. Eso puede marcar una gran diferencia más adelante y simplificar mucho su diseño. Por supuesto, una vez que tenga la interfaz de fábrica en su lugar, puede cambiar fácilmente su representación interna de sus productos de funciones simples a funtores (y viceversa).

+0

Gracias. La fábrica tiene más sentido. ¿Qué tal fábrica devuelve el puntero de función en lugar de una instancia polimórfica? –

+0

@Appu Ver mi actualización. –

+0

Gracias a todos por la ayuda. Realmente lo aprecio. –

5

Suele ser un caso de uso bendecido para clases abstractas y funciones virtuales. No entiendo por qué lo considera una "sobre-ingeniería" ... o_O

El punto es definir un contrato para que su código sea extensible fácilmente, y el "código principal" no tenga preocuparse por los detalles de la implementación real.

2

Cualquiera de las soluciones es válida para el problema tal como lo ha indicado. La fábrica es probablemente más bonita si el espacio problemático crece en absoluto. Por ejemplo, si necesita otra clase o función dependiente del idioma en el futuro, puede ampliar la fábrica para devolverla también. La tabla de indicadores de función requeriría más cambios para manejar algo así. Yo iría con una fábrica. Los dominios problemáticos siempre crecen.

Cuestiones relacionadas