Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the advantage of hiding new from client by factory design pattern

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.

like image 645
NDestiny Avatar asked Dec 22 '14 07:12

NDestiny


1 Answers

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.

like image 152
Angew is no longer proud of SO Avatar answered Oct 07 '22 06:10

Angew is no longer proud of SO