2
votes
\$\begingroup\$

I am trying to use a map as a way to implement an object factory. In Python it is possible to store a class type in a map, and use it later to create objects from that type:

class Foo:
    # ...

class Bar:
    # ...

factory_map = { 'foo' : Foo, 'bar' : Bar }
foo_object = factory_map['foo']()

I am not aware of a similar feature (i.e., storing a type in a map) in C++, so I came up with a solution based on lambda functions where the map stores functions responsible to create the objects:

class Base {
public:
    typedef std::unique_ptr<Base> Pointer;
    virtual void hi() = 0;
};

class Foo : public Base {
public:
    void hi() { std::cout << "Hi, it's foo\n"; }
};

class Bar : public Base {
public:
    void hi() { std::cout << "Hi, it's bar\n"; }
};

int main() {
    std::map<
        std::string,
        std::function<Base::Pointer()>> factory_map = {
            { "foo", []() { return Base::Pointer(new Foo()); } },
            { "bar", []() { return Base::Pointer(new Bar()); } },
        };

    Base::Pointer b1 = factory_map["foo"]();
    b1->hi();

    Base::Pointer b2 = factory_map["bar"]();
    b2->hi();
}

This might be the most straightforward solution to obtain Python's simplicity. I am wondering, however, if the usage of lambdas is the best way to create the factory. Specifically, I would like to know what are the pros/cons of this approach compared to a more "traditional" factory design (i.e., one using if/else conditionals to decide the type of the object to create).

\$\endgroup\$

locked by Jamal Aug 10 '14 at 0:02

This question exists because it has historical significance, but it is not considered a good, on-topic question for this site so please do not use it as evidence that you can ask similar questions here. This question and its answers are frozen and cannot be changed. See the help center for guidance on writing a good question.

Read more about locked posts here.

  • \$\begingroup\$ I would not say if/else is more traditional. I would say that using a map was more traditional (were do you think python got that pattern from). \$\endgroup\$ – Martin York Aug 15 '12 at 17:26
  • \$\begingroup\$ @LokiAstari Well, in many places I have seen factories implemented with conditionals. One example could be the C++ example in Wikipedia. \$\endgroup\$ – betabandido Aug 15 '12 at 18:26
  • 1
    \$\begingroup\$ Sure you can do it with conditionals just like you can in Python. Its an easy way to explain the concept this way. But in the real world you would use a map as you can add factory functions dynamically. Also I don't think wikipedia is not a great source for good examples. It is a good point to start research on a subject but follow the links to more authoritative pages (like SO). \$\endgroup\$ – Martin York Aug 15 '12 at 19:50
  • 1
    \$\begingroup\$ Maybe try something like this self-registering factory. \$\endgroup\$ – Kerrek SB Aug 17 '12 at 17:10
2
votes
\$\begingroup\$

The common argument for preferring one over the other for a dictionary (map) look up and a conditional (switch) look up is performance over maintainability.

The dictionary look up usually makes it easier to separate concerns. It also makes the code more concise and arguably more readable when invoking the factory functions.

The conditional look up avoids traversing a map and any types of indirection allowing for arguably faster access to object creation. It also avoids the overhead of creating the map/registering functions in the map.

There are also arguments for locality of reference vs. dependency management where the switch statement may keep object creation local to the call site, while the map approach passes off creation to a function or object that knows how to better handle the problem.

These are the typical arguments that I see for each of those different approaches to this problem.

\$\endgroup\$
1
vote
\$\begingroup\$

It sounds like you're trying to achieve a sort of RTTI context? What are you trying to accomplish with the type checking you're doing?

C++ is a strongly typed language and usually 'type checked' code can be rewritten into a templated interface or class hierarchy with inheritance. Sometimes there is code where type checking is unavoidable though.

(software engineering note: C++ is not Python and should be treated as such).

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.