C++ 使用工厂朋友类分配新类,好的做法?

C++ 使用工厂朋友类分配新类,好的做法?,c++,factory,friend,C++,Factory,Friend,我有一个复杂的类,我想强制用户使用std::unique_ptr,我认为最好的方法是创建一个工厂方法,返回std::unique_ptr并隐藏ctor 问题是,我添加的工厂方法越多,头和代码看起来就越脏 所以我想,如果我创建一个包含所有工厂方法的新类工厂类,它看起来会更干净,每次我想添加一个新工厂方法时,我只需编辑工厂类并完成它(保持原始类干净) 例如: class Widget { private: friend class WidgetFactory; Widget(){}

我有一个复杂的类,我想强制用户使用std::unique_ptr,我认为最好的方法是创建一个工厂方法,返回std::unique_ptr并隐藏ctor

问题是,我添加的工厂方法越多,头和代码看起来就越脏

所以我想,如果我创建一个包含所有工厂方法的新类工厂类,它看起来会更干净,每次我想添加一个新工厂方法时,我只需编辑工厂类并完成它(保持原始类干净)

例如:

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; }
};
另一种方法是使用私有令牌使ctor显式公开,这样我就可以使用std::make_shared/unique

但我不记得以前见过这种模式,所以我的问题是,这是好的做法吗?你介意从你的同事那里看到这样的代码吗


提前感谢。

不,这不是一个好做法:

  • 您将无法为单元测试创建这样的对象-您必须使用工厂
  • 对任何东西使用
    std::unique_ptr
    都会让人想起这样一句话:“当你有一把新锤子时,一切看起来都像钉子”。它有很好的用途,但并不能解决所有问题
  • 带有
    auto
    的代码看起来不错,但是您不能使用它来创建成员变量
  • 对于大型(或至少是中型)项目来说,使用一个工厂来完成所有事情将变得非常麻烦,并且将无法达到其目的

  • 工厂模式很好(我个人也很喜欢),但我不认为每个对象都需要使用它来创建。

    为什么不为
    小部件定义移动构造函数和移动赋值操作符呢?然后你可以用右值设置一个唯一的ptr。谢谢你的回答。很抱歉,但我不明白这有什么帮助,我应该在哪里用右值设置一个唯一的ptr?这意味着我必须构建所有的CTOR(而不是工厂方法)并正确操作?谢谢你的回答。从来没有想过单元测试这是一个好观点。我知道这个类看起来很简单,但我正在处理的是一个C包装器,它有很多指针和函数,可以处理这些指针。所以我应该坚持使用构造函数?但是如果我使用10个不同的构造函数,这会不会让我的代码看起来更糟?另外,复制和移动并不总是琐碎的,创建起来可能会很痛苦,这就是我选择std::unique的原因_ptr@sap您仍然可以将工厂模式与std::unique_ptr一起使用,只是不要隐藏构造函数。不要对所有对象使用一个工厂。@sap通常情况下,工厂将用于运行时多态性,例如,使用公共接口创建具体类。每个具体类都有一个
    create()
    函数,工厂类将存储这些创建者的函数指针注册表。可以在运行时探测注册表,查看必须将哪个特定的具体类分配给
    std::unique\u ptr
    。creator函数只返回一个
    std::make_unique
    。但是您希望构造函数是公共的,因为知道要生成哪个类的客户机应该能够在不使用
    唯一\u ptr
    的情况下这样做。
    int main(int argc, char** argv)
    {
        auto w = WidgetFactory::create();
        w->printMessage();
    }