依赖注入和运行时对象创建

时间:2009-03-05 00:27:53

标签: c++ dependency-injection

我一直在尝试遵循依赖注入的原则,但是after reading this article, I know I'm doing something wrong.

以下是我的情况:我的应用程序收到不同类型的实体邮件。所有传入的邮件都通过我的MailFunnel对象。

当它正在运行时,MailFunnel会从外部接收不同类型的消息:Box,Postcard和Magazine。

每种邮件类型都需要以不同方式处理。例如,如果Box进来,我可能需要在交付之前记录重量。因此,我有BoxHandlerPostcardHandlerMagazineHandler个对象。

每次有新消息进入MailFunnel时,我都会实例化一个对应的MailHandler对象。

例如:

class MailFunnel
{
  void NewMailArrived( Mail mail )
  {
    switch (mail.type)
    {
      case BOX:
        BoxHandler * bob = new BoxHandler(shreddingPolicy, maxWeightPolicy);
        bob->get_to_work();
        break;

      case POSTCARD:
        PostcardHandler * frank = new PostcardHandler(coolPicturePolicy);
        frank->get_to_work();
        break;

      case MAGAZINE:
        MagazineHandler * nancy = new MagazineHandler(censorPolicy);
        nancy->get_to_work();
        break;
    }
  }

  private:
    MaxWeightPolcy & maxWeightPolicy;
    ShreddingPolicy & shreddingPolicy;
    CoolPicturePolicy & coolPicturePolicy;
    CensorPolicy & censorPolicy;
}

一方面,这很好,因为这意味着如果我收到五封不同的邮件,我会立即有五个不同的MailHandlers同时处理业务。但是,这也意味着I'm mixing object creation with application logic - 在依赖注入方面是一个很大的禁忌。

此外,我在MailFunnel对象中MailFunnel确实不需要所有这些政策参考。 MailFunnel具有这些对象的唯一原因是将它们传递给MailHandler构造函数。再次,this is another thing I want to avoid

欢迎所有建议。谢谢!

4 个答案:

答案 0 :(得分:8)

这看起来更像是我的工厂。将get_to_work()方法的调用移出调用并返回处理程序。该模式适用于工厂。

class MailHandlerFactory
{
  IMailHandler*  GetHandler( Mail mail )
  {
    switch (mail.type)
    {
      case BOX:
        return new BoxHandler(shreddingPolicy, maxWeightPolicy);
        break;

      case POSTCARD:
        return new PostcardHandler(coolPicturePolicy);
        break;

      case MAGAZINE:
        return new MagazineHandler(censorPolicy);
        break;
    }
  }

  private:
    MaxWeightPolcy & maxWeightPolicy;
    ShreddingPolicy & shreddingPolicy;
    CoolPicturePolicy & coolPicturePolicy;
    CensorPolicy & censorPolicy;
}

class MailFunnel
{
    MailHandlerFactory* handlerFactory;

    MailFunnel( MailHandlerFactory* factory ) {
        handlerFactory = factory;
    }

    void NewMailArrived( Mail mail ) {
        IMailHandler handler = handlerFactory.GetHandler(mail);
        handler.get_to_work();
    }
}

答案 1 :(得分:2)

为什么你不能只有三个重载的方法来接收不同类型的邮件,然后做适当的事情?或者让每种类型处理自己。

事实上,如果你有类似的东西,你可能实际上应该有不同的类型。

基本上做以下事情:

1)使Mail类抽象化。

2)创建三个子类邮件,Box,PostCard和Magazine

3)为每个子类提供一个处理邮件的方法,或者将其集中在一个单独的HandlerFactory中

4)当传递给邮件渠道时,只需让它调用句柄邮件方法,或者让HandlerFactory将邮件传递给它,然后获取相应的处理程序。同样,不要在任何地方使用笨拙的switch语句,而是使用该语言,这就是重载的类型和方法。

如果您的邮件处理变得复杂并且想要将其删除,您最终可以创建一个邮件处理程序类并将这些策略提取到该文件中。

你也可以考虑使用模板方法,因为每个方法之间唯一真正的区别似乎是你实例的处理程序,也许你可以简化它,这样邮件类型决定了处理程序,其余的代码是基本相同。

答案 2 :(得分:2)

当你看到switch语句时,想想多态。此设计只能通过修改来扩展。我会以这样的方式重做它,以便通过添加类来添加新行为。这就是开放/封闭原则的全部内容。

答案 3 :(得分:1)

有趣的是你将依赖注入应用于C ++项目;它已在其他地方完成,快速Google搜索会找到Google代码项目Autumn Framework

但在采用新框架之前,tvanfosson的回答是我建议首先尝试的。