Martijn Pot
Martijn Pot

Reputation: 86

Split Factory (pattern) over multiple libraries

As I can't use the real code, I'll try to sketch the situation using a simplified pseudo-code example:

class Factory {
public:
    System& build(const Input& input) {
        if (input.getType() == "Airplane") return Airplane(input.getNrWheels);
        if (input.getType() == "Car") return Car(input.getNrWheels);
    }
}

Both Car and Airplane inherit from System;

We use this factory in two executables. As executable 1 can be used with Cars and executable 2 can be used with Airplanes. We would like to be able to compile and link executable 1 with Factory and Car and executable 2 with Factory and Airplane. What should we do with the Factory class to enable this?

EDIT: Change after comments/answers

This is less simplified example showing my problem more clearly:

class Factory {
public:
    System& build(const Input& input) {
        if (input.Airplane()) {
            Pilot& pilot         = *new Pilot();
            AutoPilot& autoPilot = *new AutoPilot();
            return Airplane(input.Airplane()->NrWheels(), pilot);
        }
        if (input.Car()) {
            Driver& driver = *new Driver();
            return Car(input.Car()->NrWheels, driver);
        }
    }
}

I like the answer below which suggests the constructor map, but I (think I) need a version which allows different arguments for the constructors. I also would like to keep Car and Airplane free of dependency on Input.

Upvotes: 0

Views: 99

Answers (2)

Puppy
Puppy

Reputation: 146930

Cut it out completely. The Factory class serves literally no benefit at all when it can only create one kind of thing. Just use a typedef instead to be flexible about what kind of System you are creating.

Upvotes: 0

Pradhan
Pradhan

Reputation: 16737

Use something like a std::map<std::string, std::function<System(T)> ctorMap; where T is the type of Input::getNrWheels, inside Factory to hold the appropriate constructors, indexed by strings. Also provide a method, say Factory::Register(std::string, std::function<System(T)) which any class can use to register its constructor. So, the TU which defines Airplane should ensure that there is a call, during static initialization, for example, Factory::Register("Airplane", std::make_function(&Airplane::Airplane)).

Also, Factory::build would now look like this:

System& build(const Input& input) {
     return ctorMap[input.getType()](input.getNrWheels);
    }

Upvotes: 1

Related Questions