这个丑陋的构造函数/工厂有没有C ++成语?

时间:2015-08-28 19:00:01

标签: c++ factory v8 c++14

我有一些看起来像这样的代码:

class Widget {
  public:
    static std::unique_ptr<Widget> make(OtherArgs args);  // factory pattern

    Widget(v8::isolate&& isolate, OtherArgs args);
  private:
    v8::Local<v8::Object> Widget::create_v8_object()

    v8::isolate isolate_;
    v8::Local<v8::Object> gadget_;
};

std::unique_ptr<Widget> Widget::make(OtherArgs args)
{
    v8::isolate isol;
    v8::HandleScope scope(isol.get());
    return std::make_unique<Widget>(std::move(isol), args);
}

Widget::Widget(v8::isolate&& isol, OtherArgs args) :
    isolate_(std::move(isol)),
    context_(isolate_.get()),
    gadget_(isolate_.get(), create_v8_object())
{
}

v8::Local<v8::Object> Widget::create_v8_object()
{
    v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate_.get());
    // ...
    v8::Local<v8::Object> gadget = v8::Local<v8::Object>::New(isolate_.get(), tmpl->NewInstance());
    // ...
    return gadget;
}

int main()
{
    auto widget = Widget::make(some_args);
    // ...
}

但是,三行Widget::make功能很难看 - 它是创建Widget个对象的单一“祝福”方式,但we cannot make the Widget constructor private because Widget::make is implemented in terms of make_unique

但是,如果我们可以让我们的Widget构造函数本身创建“祝福”对象,我们可以将main()更改为

int main()
{
    auto widget = std::make_unique<Widget>(some_args);
    // ...
}

它将全部正常工作,没有工厂功能。

我遇到的问题是,我认为我们需要v8::HandleScope围绕v8::Local<T>create_v8_object()内部HandleScope的构造,该handleScope_是从构造函数的成员初始化程序调用的 - 名单。我们需要一种在执行成员初始化器之前创建isolate_ 的方法,然后在构造函数的末尾销毁它。

我正在寻找一种方法来解决这个问题,最大限度地提高代码清晰度。 (例如,我可以在类中添加一个成员HandleScope,并确保其成员初始化程序是列表中的第一个(嗯,第二个,在Widget::make之后);但这会使类的大小我不知道如何在构造函数的末尾清理它。

我还想过将Widget::create_v8_object()EscapableHandleScope向下移动到return scope.Escape(gadget),在那里它会成为create_v8_object而我们会x。但是,如果我有很多y次呼叫,那么所有这些HandleScopes都会造成性能损失,还是会产生其他任何不良影响?

1 个答案:

答案 0 :(得分:1)

如何委派构造函数?

class Widget {
private:
    Widget(v8::isolate && isol, v8::HandleScope scope, OtherArgs args) { /* ... */ }
    Widget(v8::isolate && isol, OtherArgs args) : Widget{std::move(isol), {isol.get()}, args} { }
public:
    Widget(OtherArgs args) : Widget{{}, args} {}
};