C ++中构造函数注入的高级配置

时间:2013-11-27 15:16:09

标签: c++ testing dependency-injection constructor-injection

我的问题是通过构造函数专门处理依赖注入。我理解服务定位器模式,构造函数/ setter注入及其风格的优缺点,但是在选择纯构造函数注入之后,我似乎无法通过。在阅读了许多可测试设计的材料之后,包括彻底浏览MiškoHevery的博客(特别是this帖子),我遇到以下情况:

假设我正在编写一个C ++程序,并且我已经通过它们的构造函数正确地注入了我的依赖项。为了便于阅读,我给自己一个高级对象,它有一个从main调用的Execute()函数:

int main(int argc, char* argv[]) {
    MyAwesomeProgramObject object(argc, argv);
    return object.Execute();
}

执行()的职责是简单地连接所有必需的对象并启动最高级别的对象。最高级别的对象需要一些依赖项,这些对象需要一些对象等等,这意味着一个如下所示的函数:

MyAwesomeProgramObject::Execute() {
    DependencyOne one;
    DependencyTwo two;
    DependencyThree three;

    MidLevelOne mid_one(one);
    MidLevelTwo mid_two(two, three);

    // ...

    MidLevelN mid_n(mid_dependencyI, mid_dependencyJ, mid_dependencyK);

    // ...

    HighLevelObject1 high_one(mid_one, mid_n);
    HighLevelObject2 high_two(mid_two);

    ProgramObject object(high_one, high_two);
    return object.Go();
}

我从Miško的博客中得到的内容(我会问他,但认为他没有时间回复我),这是满足纯构造函数注入依赖项的唯一方法。

在博客文章mentioned中,他声明我们应该在每个对象的生命周期级别上拥有工厂,但这基本上是Execute正在做的事情,使我的代码看起来与他的例子相同:

AuditRecord audit = new AuditRecord();
Database database = new Database(audit);
Captcha captcha = new Captcha();
Authenticator authenticator =
    new Authenticator(database, captcha, audit);
LoginPage = new LoginPage(audit, authenticator);

问题:

  • 这是正确的方法吗?
  • 这是一个我不知道的模式(看起来与Maven的context.xml类似)?
  • 对于纯构造函数注入,我是否只是遭受“前期”分配的成本?

1 个答案:

答案 0 :(得分:0)

请注意,您的不同示例是矛盾的。首先,您将在堆栈上显示创建对象,最后一个示例将分配对象。

堆栈上的对象有点危险,但在大多数情况下都很好。主要问题是当该对象来自堆栈时,给另一个具有比函数更长的生命周期的对象作为对象指针...当该长生命对象在函数返回后尝试访问堆栈上的对象时,你有一个问题。如果所有对象都有堆栈生命周期,那么你没事。

就个人而言,我开始使用共享指针,我发现这是最终简化大量对象的管理。

std::shared_ptr<foo> foo_object(new foo);
std::shared_ptr<blah> foo_object(new blah(foo));

这样,blah可以永久保存foo共享指针的副本,一切都按预期工作,即使在函数边界之间也是如此。不仅如此,共享指针在创建时为NULL,并在删除时自动删除(当然,当删除最后一个共享指针时。)并且您可以在不需要始终设置指针的对象中使用弱指针。 ..

否则,我认为你想要做的事情在某种程度上起作用。在我的世界中,通常是事情在以后创建,所以我需要一个二传手。但是,构造函数注入对于强制用户正确初始化对象非常有用(即我经常创建只读对象,没有setter,在构造时100%初始化,非常实用,非常安全!)