I have read the factory design pattern recently, in that he had mentioned one of the problem in normal approach is
*Need to use the new keyword in client classes.
So by using factory we have achieved this (client doesn't use new). But what is the advantage of hiding new from the client?
One problem is when client uses the new key word, he is then responsible to delete that memory. Any how if we use factory also, we still need to do that, when client creates a object at the end the client has to delete it (factory wont delete them).
I understand, other advantages like, reusing the existing code and no need to change client side code. but I got confused what we have achieved by hiding new (or even class) from client.
Thanks in advance.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With