我一直在尝试遵循依赖注入的原则,但是after reading this article, I know I'm doing something wrong.
以下是我的情况:我的应用程序收到不同类型的实体邮件。所有传入的邮件都通过我的MailFunnel
对象。
当它正在运行时,MailFunnel
会从外部接收不同类型的消息:Box,Postcard和Magazine。
每种邮件类型都需要以不同方式处理。例如,如果Box进来,我可能需要在交付之前记录重量。因此,我有BoxHandler
,PostcardHandler
和MagazineHandler
个对象。
每次有新消息进入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。
欢迎所有建议。谢谢!
答案 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的回答是我建议首先尝试的。