创建类时的依赖注入还需要运行时值吗?

时间:2010-06-25 12:03:59

标签: oop dependency-injection singleton injectable newable

假设您在Value对象和Services对象中划分系统(如“面向对象的软件增长,测试指导”中所述.Misko Hevery称这些为“newables”和“injectables”。

如果您的某个值对象突然需要访问服务来实现它的方法,会发生什么?

假设你有一个很好的简单Value对象。它是不可变的,包含一些信息,而且就是它。假设我们使用类似这样的东西:

CreditCard card = new CreditCard("4111-1111-1111-1111", "07/10");
if (card.isValid())
{
  // do stuff
} 
else
{
  // don't do stuff
}

到目前为止一切顺利。 isValid()在卡号上实现校验位算法并返回true / false。

现在,假设我希望通过验证当前时间的到期日来增强系统。您如何在不破坏Value对象/服务对象paradim的情况下完成此操作?我希望这个课程能够继续进行单元测试。

  • CreditCard现在有一个依赖项,但由于它的创建方式,它无法注入,因此依赖注入已经完成。
  • CreditCard课程不应该呼唤单身人士(我认为全球访问单身人士是不好的做法)
  • 将行为放在CreditCardVerificationService.validateCard()上意味着必须重新访问所有现有代码。 isValid()的实现正在泄漏。

我知道可以采取一些措施来解决这个问题,但最简洁的方法是什么?

3 个答案:

答案 0 :(得分:4)

我认为验证任何东西都不是CreditCard对象的工作。工厂将验证校验位以确保它实例化符合要求的卡,而验证服务将验证卡是否到期/ $ limit。

答案 1 :(得分:1)

我很想说CreditCard不是价值对象。

来自C2 wiki

  

价值对象的例子就是事物   喜欢数字,日期,钱和   字符串。通常,它们很小   广泛使用的对象。   他们的身份是基于他们的国家   而不是他们的对象身份。   这样,您就可以拥有多个副本   相同的概念价值对象。

     

值对象不是   BusinessObject的/ ReferenceObject。一个   BusinessObject / ReferenceObject是   你在世界上找到的东西,而   ValueObject是一个度量或   对某事的描述。

如果CreditCardNumber可能是值对象,CreditCard看起来更像是包含某些业务逻辑的业务对象,例如验证

我通常拥有价值对象,服务和业务对象。我不知道“增长的面向对象的软件”,但限制自己仅限于价值对象和服务对我来说似乎很奇怪。

答案 2 :(得分:0)

我会将CreditCard称为实体而不是值对象,因为它可能是持久的并且具有唯一的身份。

无论如何,实体类使用服务类应该是完全正确的。如果不需要在运行时基于外部配置选择所述服务的实现,那么我将简单地在客户端方法中实例化并使用所需的服务类。与某些人的想法相反,这并不排除单元测试,因为可以使用模拟工具进行隔离。

如果需要在运行时选择服务实现 ,则可以使用服务定位器。这种模式可以为模拟/伪造提供直接支持,而无需专门的模拟工具。使用支持注入“新”对象的DI框架将是另一种选择。