views:

85

answers:

3

I am working on a transliteration tool. I have two modules lexer and translator. Lexer generates tokens out of the input text. Depending on the current language chosen, I have to call appropriate translation routine.

I have came up with couple of ideas to do this. First one is to create a base class something called base_translator and provide virtual method (translate()) which every translators has to override. Now create a factory translator_factory and call create() with the language name. This factory will return appropriate instance.

But this seems to be over engineering. So I came up with another approach where I have a struct like the following.

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

Which just keeps a language name and a function pointer who can process it. Usage will be,

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

This approach is very simple and easy to maintain. But I wonder, is this the best approach to the problem? Do you have any suggestions to make this better?

Any help would be great.

+5  A: 

This is typically a blessed use-case for abstract classes and virtual functions. I don't get why you think of it as "over-engineering".... o_O

The point is to define a contract so that your code is extensible easily, and the "main code" doesn't have to worry about the actual implementation details.

Romain
+3  A: 

Your second approach might look simpler to you for just two items (well for me it doesn't...), but it is more error-prone and difficult to maintain in the long run. Whenever you add a new language, you need to touch the code in at least two places. (And trust me: even if this seems unlikely to you at the moment, it is almost inevitably going to happen...) If you forget to update your loop boundary, you have a silent bug in your code. Moreover, this implementation is much slower than a polymorphic one: you need to iterate over the array and compare character strings before each call (as opposed to looking up a pointer in the vtable).

I would definitely use a factory. Apart from the benefits above, it is a well known design pattern which makes it easier to understand. Thus people coming after you to maintain your code will not curse you that much ;-)

Update: A factory can also return a function pointer. In this case I would still use functors internally, because these are full fledged classes with all the benefits listed above. And one more, not explicitly mentioned: they (as real objects) can store state, which plain functions can't. That may make a big difference later, and simplify your design a lot. Of course, once you have the factory interface in place, you can easily change your internal representation of its products from plain functions to functors (and back).

Péter Török
Thanks. Factory makes more sense. How about factory returns the function pointer rather than a polymorphic instance?
Appu
@Appu See my update.
Péter Török
Thanks all of them for the help. I really appreciate it.
Appu
+2  A: 

Either solution is valid for the problem as you've stated it. The factory is probably nicer if the problem space grows at all. For example, if you need yet another language dependent class or function in the future, you can extend the factory to return that as well. The table of function pointers would require more changes to handle something like that. I'd go with a factory. Problem domains always grow.

Adrian McCarthy