当方法需要创建新对象时,有关依赖注入的新手问题

时间:2009-06-10 22:57:17

标签: language-agnostic dependency-injection

我一直在阅读有关依赖注入的内容,并提出了一个简单的问题。我可以理解如何通过构造函数或setter注入所需的依赖项由DI框架自动装配。当对象决定由于某些业务流程而需要创建新对象时会发生什么?在这些情况下,我是否需要始终创建工厂?为了使它成为一个不那么抽象的问题,这是一个例子。

假设我正在写一个Asteriods游戏。中间有一艘船可以旋转并射击星号。假设已经创建了船并注入了适当的东西。调用playerShip.shoot()时,我们需要创建一个bullet对象。子弹对象需要知道它的走向(direction)以及从哪里开始(point)。

通常情况下,我会这样做:

bullet = new Bullet( direction, point );

然而,这将PlayerShip类与Bullet类紧密耦合。这应该如何在依赖注入下工作?我是否需要创建一个BulletFactory接口并将其实现注入到船中?

编辑:我实际上并没有写星号。这是一个我认为人们会理解的简单例子。我想要一些需要创建运行时的东西(不是在“连接对象”时),它也有参数给它的构造函数。

4 个答案:

答案 0 :(得分:3)

取决于你是否只有一种子弹类型......

如果只有一个,那么我会说你没事。

但如果您有子弹,DoubleBullet,PowerBullet,NukeBullet等

然后我会制作Bullet基类和其他所有Derrived

然后我会制作Bullet工厂,它会有CreateBullet,CreatePowerBullet等。

另一个问题是其他任何事情都会成为一颗子弹吗?如果是这样,那么我会创建一个工厂来合并创建逻辑......

否则它就像使用DI一样,只是为了使用DI ......

答案 1 :(得分:2)

你已经得到了它。如果你想与Bullet类解耦,那么在我看来,最好的解决方案是注入一个可以创建Bullet个对象的工厂。

请注意,您可以采用多个级别的间接,每个级别都可以提供更多灵活性,但需要更多代码并且可能更难以理解。最简单的是让BulletFactoryBullet都是具体类型。这意味着您不能轻易地拥有它们的不同实现,但您仍然可以扩展它们并传入BulletFactory的子类,该子类返回Bullet的子类。如果您注射的唯一目的是使单元测试更容易,这就是我要采取的路线。当然,您也可以使BulletFactory成为界面,或Bullet界面,或两者兼而有之。如果您要为非测试目的使用不同的工具,这就是我要采取的路线。

最后,您必须确定将Bullet类与PlayerShip类解耦的好处是否值得。紧耦合不是邪恶的,不应该不惜一切代价避免 - 它在某些情况下是有道理的,而在其他情况下则不然。只有经验才能帮助您确定何时结合课程以及何时将其分离。

答案 2 :(得分:1)

依赖注入不适合这种情况。如果您为此创建工厂,则会过度使用设计模式。你不能解耦整个系统,在这种情况下,Ship有一个带有Bullet的组合,如果你需要更复杂的东西,那么另一个模式(不一定是DI)就足够了。

答案 3 :(得分:1)

是的,这闻起来像过度架构。然而,在我的头脑中,你可以拥有一个存储子弹类型的属性,然后让你的DI框架(这里是ninject)创建子弹。

public Type BulletType {get; set;}

public void fire()
{
    var b = (BulletType) kernel.get(BulletType);
    b.fire(point, direction);
}