What is the advantage of hiding a factory-design pattern from a customer?

I recently read a factory design template, as it mentioned one of the problems with the normal approach

* You must use the new keyword in client classes.

So, using the factory, we have achieved this (the client does not use a new one). But what is the advantage of hiding the new from the client?

One of the problems is that the client uses the new keyword and then is responsible for deleting this memory. Anyone how we use the factory, we still need to do this when the client creates an object at the end, the client must delete it (factory do not delete them).

I understand other benefits, such as reusing existing code and not having to change the code on the client side. but I got confused about what I achieved by hiding from the client a new (or even cool) one.

Thanks in advance.

+6
source share
4 answers

I do not think that the main purpose of the factory template is to "hide new from the client." The main goal is to "hide what new used and how." This gives you the freedom to choose in your implementation which class you will actually create.

For example, you can suggest a Renderer interface in a 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 ++, the added benefit of providing a factory function is to ensure proper memory management. If you changed the code above to return std::unique_ptr<Renderer> (what needs to be done correctly), you protect the client from Murphying a memory leak (what they could do without calling delete on the return value in the case of an unhandled pointer) 1 .

You might want your factory to retain partial ownership of the object (so that it can reuse them), so you would 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 summarize, factory design patterns (Annotation factory and factory) give you more control over how creation and initialization work.


1 Of course, they can still Machiavelli leak memory by running createRenderer().release() , but then this is an active action on their part, and not just inaction.

+4
source

Factory template is not intended to hide the use of new from the client. And yes, you have to call delete on the object called by the new in the factory.

The main advantage of the factory template is that it localizes the creation of an object in one place. Thus, any changes in the hierarchy can affect only this large part of the code, which is only a specialization of the general rule that any changes in the software should affect the minimum part of the code.

+2
source

One of the advantages is that you do not need to worry about any dependencies required to create the object. Using a factory, you can simply abstract all the necessary links. This is due primarily to the fact that the client does not need to create and do not know the details necessary for assembly.

0
source

Factory templates (a simple factory, factory, and abstract factory method) have all the advantages of hiding the details of creating a product from customers. This is more than just new , although this keyword often appears when creating objects. There are many other details, such as subclass name, constructor options, etc. The fact is that you want to hide this information from the client, because if it changes, you will only update it in the factory (unlike the code in all clients if there was no factory).

The essence of your question is that the responsibility for processing memory does not disappear, even if the client does not use the new operation.

Have questions about SO:

I personally like the idea that if a factory is responsible for encapsulating the creation of an object, then it should also encapsulate responsibility for not creating it. That is, it should have something like a delete method (opposite create ).

0
source

Source: https://habr.com/ru/post/980021/


All Articles