Question Details

No question body available.

Tags

c++ object-oriented-design factory

Answers (3)

Accepted Answer Available
Accepted Answer
September 18, 2025 Score: 4 Rep: 4,567 Quality: Medium Completeness: 40%

If creation process depends on a local context, do not use global factory. Another, special, factory may be used for special checks and actions or none at all.

Factory factory; FactoryA factoryA; std::string typeName= "a"; if (typeName == "a") { // Creates, does checks and special actions, may be inlined newBase = factoryA.CreateA(Params); } else { newBase = factory.CreateBase(typeName, Params); }
September 18, 2025 Score: 1 Rep: 220,789 Quality: Medium Completeness: 60%

Ideally, the factory should be the only point in your code which knows of the specific subtypes of Base, like the subtype A, and its methods, and how each subtype is constructed. It is reasonable it knows that under certain conditions DoSomethingSpecific() needs to be called during construction of A. Still, since these conditions depend on something out of the scope of the factory, you may pass the condition checker into the factory by functional means.

In other words, I would simplify your AddSpecialCase approach to an AddSpecialCondition approach: instead of

AddSpecialCase(std::function SpecialCondition,
               std::function ActionIfSpecial)

just add a method

 AddSpecialCondition(std::function SpecialCondition)

and use this during creation, analogously to the way showed in your question.

The important difference to your approach is, the caller does not need to have any knowledge about which subtypes Base has. AddSpecialCase had a parameter which depends on A at compile time. AddSpecialCondition has not. Passing just the SpecialCondition function into the factory does not make the caller depend on A.

The caller may know that SpecialCondition is called for the construction of certain subtypes, but it does not know for which precisely, or how this is implemented exactly. Maybe the author of the calling code has a notion in their head of what happens "behind the scenes", still this avoids the compile time dependency of A in the caller.

September 18, 2025 Score: 0 Rep: 85,137 Quality: Medium Completeness: 60%

I think the "generic" approach might be the builder pattern.

a = Factory.Create("a")
           .WithParams(p)
           .WithSpecial(s)
           .UsingWidget(w)
           ....
           .Build()

You raise the issue that if the type isn't "a", then WithSpecial either does nothing or errors. This pushes the conditional back to the caller

base = Factory.Create(sometype)
           .WithParams(p)
           if(sometype == "a" && conditions) {
           .WithSpecial(s)
           }
           .UsingWidget(w)
           ....
           .Build()

I would say this is the nub of the problem, and it depends on what exactly WithSpecial is doing.

If A + WithSpecial is effectively just another variant of Base that the caller shouldn't know about, then you can put that conditional in the factory.

If A + WithSpecial is an optional configuration of A that the caller would be expected to know about, then the conditional should be with the caller.

If you have many conditions and parameters that may or may not apply to the various subclasses produced by the factory, then it's fine for the builder pattern to just do nothing when WithSpecial is called on a "b" or other class that doesn't support it.

This last case, to my mind, is the "generic" one because you can add as many With.. and Using... methods as you like without breaking existing code by requiring different parameters in the constructor