Search code examples
c++factoryfriend

use factory friend class to allocate new class, good practice?


i have a complex class that i want to force the user to use std::unique_ptr for it, the way i see it the best way is to create a factory method that returns a std::unique_ptr and hide the ctor.

problem is, the more factory methods i add the dirtier the header and code starts to look.

so i thought maybe if i create a new ClassFactory class that has all the factory methods inside it, it would look cleaner and every time i want to add a new factory method i just edit the factory class and be done with it (leaving the original class clean).

for example:

class Widget
{
private:
    friend class WidgetFactory;

    Widget(){}
    Widget(const Widget& other) = delete;
    Widget& operator = (const Widget& other) = delete;

    std::string _msg;

public:
    void printMessage(){ std::cout << _msg << std::endl; }
};

class WidgetFactory
{
public:
    static std::unique_ptr<Widget> create(){ auto w = std::unique_ptr<Widget>(new Widget);
                                             w->_msg = "hello world!"; return w; }
};

and then the user:

int main(int argc, char** argv)
{
    auto w = WidgetFactory::create();
    w->printMessage();
}

another way is to make the ctor explicit public with a private token so i can use std::make_shared/unique.

but i dont recall seeing this pattern before, so my question is, is this good practice? would you mind seeing code like this from your coworkers?

thanks in advance.


Solution

  • No, it is not a good practice :

    1. you will not be able to create such objects for unit testing - you would have to use the factory
    2. using std::unique_ptr for everything reminds of the saying "when you have a new hammer, everything looks like a nail". It has a good use, but it doesn't solve all problems
    3. the code with auto looks nice, but you can not use it to create member variables
    4. for big (or at least medium) projects, using one factory for everything is going to become very cumbersome, and is going to defeat it's purpose

    The factory pattern is good (and I personally like it), but I don't think that literally every object needs to be created using it.