I don't think the primary purpose of the factory pattern is to "hide new
from the client." The primary purpose is to "hide which new
is used and how." It gives you the freedom to choose in your implementation which class you'll actually create.
For example, you can offer an interface Renderer
in your factory:
class Renderer
{
// ...
};
struct RendererFactory
{
Renderer* createRenderer() const;
};
Renderer* RendererFactory::createRenderer() const
{
#ifdef WIN32
if (AskWinApiIfOpenGlEnabled())
return new OpenGlRenderer();
else
return new DirectXRenderer();
#else
return new OpenGlRenderer();
#endif
}
In C++, an additional advantage of providing a factory function is to ensure proper memory management. If you change the code above to return std::unique_ptr<Renderer>
(which is the right thing to do), you protect the client from Murphying a memory leak (which they could do by not calling delete
on the return value in the raw pointer case)1.
It's even possible you want your factory to retain partial ownership of the object (so that it can reuse them), so you'd do something like this:
class RendererFactory
{
std::weak_ptr<Renderer> cachedRenderer;
public:
std::shared_ptr<Renderer> createRenderer();
};
std::shared_ptr<Renderer> RendererFactory::createRenderer()
{
if (auto r = cachedRenderer.lock())
return r;
auto r = std::make_shared<RendererSubClass>();
cachedRenderer = r;
return r;
}
To summarise, the factory-based creation design patterns (Abstract Factory and Factory Method) give you more control over the way creation and initialisation happen.
1 Of course, they can still Machiavelli a memory leak by doing createRenderer().release()
, but then it's a active action on their part and not just omission.