views:

1025

answers:

6

I was just reading this thread and it occurred to me that there is one seemingly-valid use of that pattern the OP is asking about. I know I've used it before to implement dynamic creation of objects. As far as I know, there is no better solution in C++, but I was wondering if any gurus out there know of a better way. Generally, I run into this situation when I need to create one of several subclasses of an object based one something unknown at compile time (such as based on a config file). I use the object polymorphically once it is created.

There's another related situation when you're using a message-passing scheme (usually over TCP/IP) where each message is an object. I like to implement that pattern as letting each message serialize itself into some serialization stream interface, which works well and is fairly clean on the sending end, but on the receiver, I always find myself examining a header on the message to determine the type, then constructing an appropriate message object using the pattern from the linked article, then having it deserialize itself from the stream. Sometimes I implement it so that the construction and deserialization happen at the same time as part of the constructor, which seems more RAII, but that's small consolation for the mess of if/else statements figuring out the type.

Any better solutions out there? If you're going to suggest a 3rd party library, it should be free (and ideally open source) and I'd appreciate it if you could explain how the library accomplishes this feat.

+4  A: 

What you're describing here is termed the factory pattern. A variant is the builder pattern.

Mr Fooz
I am aware what I am talking about is called Factory pattern... I should have mentioned that. I'm talking about how to implement the guts of that pattern though. I was not aware of Builder before, but it seems to just be piecemeal Factory pattern.
rmeador
Okay, I wasn't sure you were aware of the pattern name. Both the wikipedia link as well as several other answers here have good implementation alternatives. I agree with Kenny: if you haven't picked up the GofF book yet, it's well worth the investment.
Mr Fooz
+3  A: 

I'd suggest reading the C++ FAQ Lite questions concerning serialisation and unserialisation.

There's a lot of detail in there that I cannot easily summarise in my answer, but those FAQs do cover creating objects whose types are only known at run time.

In particular:

#36.8

Although, at the most basic level, you could implement a factory similar to:

Base* Base::get_object(std::string type)
{
    if (type == "derived1") return new Derived1;
    if (type == "derived2") return new Derived2;
}
SpoonMeiser
A: 

Read the classic Gang Of Four aka GOF. Consider [this site[(http://www.dofactory.com/Patterns/PatternAbstract.aspx) for the Factory and other patterns in C#.

kenny
A: 

Unless I'm missing something, you don't need a static_cast in order to create an object whose runtime type is a subclass of the type you're supposed to be returning from your factory, and then use it polymorphically:

class Sub1 : public Super { ... };
class Sub2 : public Super { ... };

Super *factory(int param) {
    if (param == 1) return new Sub1();
    if (param == 2) return new Sub2();
    return new Super();
}

int main(int argc, char **argv) {
    Super *parser = factory(argc);
    parser->parse(argv); // parse declared virtual in Super
    delete parser;
    return 0;
}

The pattern the OP is talking about in the question you refer to is to get a Super* from somewhere, then cast it to its runtime type by examining RTTI and having if/else clauses for all the subclasses known to the programmer. This is the exact opposite of "I use the object polymorphically once it's created".

In theory, my preferred approach to deserialisation is chain of responsibility: write factories capable of looking at serialised data (including the type header) and deciding for themselves whether they can construct an object from it. For efficiency, have factories register which types they're interested in, so they don't all look at every incoming object, but I've omitted that here:

Super *deserialize(char *data, vector<Deserializer *> &factories>) {
    for (int i = 0; i < factories.size(); ++i) { // or a for_each loop
        Super *result = factories[i]->deserialize(data);
        if (result != NULL) return result;
    }
    throw stop_wasting_my_time_with_garbage_data();
}

In practice I often end up writing a big switch anyway, like this only with an enumerated type, some named constants, and maybe a virtual deserialize method called after construction:

Super *deserialize(char *data) {
    uint32_t type = *((uint32_t *)data); // or use a stream
    switch(type) {
        case 0: return new Super(data+4);
        case 1: return new Sub1(data+4);
        case 2: return new Sub2(data+4);
        default: throw stop_wasting_my_time_with_garbage_data();
    }
}
Steve Jessop
+2  A: 

I think what you are asking is how to keep the object creation code with the objects themselves.

This is usually what I do. It assumes that there is some key that gives you a type (int tag, string, etc). I make a class that has a map of key to factory functions, and a registration function that takes a key and factory function and adds it to the map. There is also a create function that takes a key, looks it up in the map, calls the factory function, and returns the created object. As an example, take a int key, and a stream that contains the rest of the info to build the objects. I haven't tested, or even compiled, this code, but it should give you an idea.

class Factory
{
    public:
    typedef Object*(*Func)(istream& is);
    static void register(int key, Func f) {m[key] = f;}
    Object* create(key, istream& is) {return m[key](is);}
    private:
    std::map<key, func> m;
}

Then in each class derived from subobject, the register() method is called with the appropriate key and factory method.

To create the object, you just need something like this:

while(cin)
{
    int key;
    is >> key;
    Object* obj = Factory::Create(key, is);
    // do something with objects
}
KeithB
For some designs, a Factory interface and implementations of it, plus a FactoryRegistry are better than functions. But it's essentially the same thing. Good one.
Arkadiy
A: 

The fundamental operation of the factory pattern is mapping an identifier to a (usually new) instance of a particular type where the type depends on some property of the identifier. If you don't do that, then it isn't a factory. Everything else is a matter of taste (i.e., performance, maintainability, extensibility, etc.).

MSN

MSN