依赖注入导致工厂激增?
自从我一直使用依赖注入原理以来,在处理需要实例化大量对象的类时,我总是感到不舒服。
例如,假设我有一个类应该引发许多不同类型的事件。每个事件都有不同的类型,所以我要做的就是为每个不同的事件类型建立一个不同的工厂。如果我有 10 个活动,那么我就必须有 10 个工厂。这看起来不太好。我也可以拥有一个工厂来处理所有不同类型的事件,但这似乎也不太正确。
(对于 C# 人群,我在这里不是在谈论 .NET 的事件。这只是一个切入主题的示例,只需将它们视为常规类即可!)
这只是一个示例。我在这里或那里拥有一个工厂没有问题,但在某些类型的项目中,必须在运行时创建大量对象,似乎我必须为我定义的几乎每个类创建一个工厂!
你如何处理这种情况?我错过了什么吗?
我见过人们只是传递对他们使用的 IoC 容器的引用,但这对我来说似乎没有任何好处。 IMO,域模型甚至不应该知道正在使用 IoC 容器!
谢谢
I have always felt uncomfortable when dealing with classes that needed to instantiate a lot of objects since I've been using Dependency Injection principles.
For instance, let's say I have a class that's supposed to raise a lot of different kind of events. Each event has a different type, so what I'd do is to have a different factory for each different event type. If I have 10 events, then I'll have to have 10 factories. That doesn't seem nice. I could also have a single factory for all the different kinds of events, but that doesn't seem too right, also.
(for the C# crowd, I'm not talking about .NET's events here. This was just an example to get to the point, just think of them as regular classes!)
This was just an example. I don't have a problem in having a factory here or there, but in certain kinds of projects where one has to create lot of objects at run-time, it seems as I have to make a factory for almost every class I define!
How do you handle this situation? Am I missing something?
I've seen people just passing around a reference to the IoC Container they use, but that doesn't seem any good to me. IMO, the domain model shouldn't even know a IoC Container is being used!
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
自从我了解 DI 以来,我就一直是构造函数注入的粉丝,因为在我看来,这就是构造函数的用途。它指出“我需要以下类/接口的实例才能完成我的工作” - 例如,传递给我一个
File
和一个PrintWriter
,我将编写以下内容前者对后者。当然,这意味着代码不知道 DI 框架,因为该类只是使用传入的所需依赖项进行构造。此外,我认为在这种情况下不需要工厂,因为该类通过构造函数是它自己的工厂。
至于您在第二段中确定的场景,我不确定这是否与依赖注入严格相关,而只是与类层次结构和职责的设计相关。 或者你的类具体知道如何创建一个
Event
来对应例如登录失败,在这种情况下它会这样做(即通过调用类的构造函数); 或者,它不知道如何做,在这种情况下,它必须委托给某种类型的工厂来创建事件
。在这种情况下,您可以将您的类设置为使用同一个工厂来创建所有十个事件(定义具有 10 个方法的
EventFactory
接口),或者您可以定义一个单独的工厂接口(和实现)对于需要构建的每种类型的事件。在后一种情况下,您还需要在主类的构造函数中传递十个不同的工厂。但再说一遍 - 这与 DI 恕我直言没有任何关系,这是一个如何设计类以实现灵活性(或“企业性”)与直接性的问题。在我看来,这两者是正交的;您首先定义您的类需要哪些协作者(十个工厂、一个工厂或零个工厂),然后使用 DI 来提供这些依赖项。 DI 的存在与否不应影响您的类设计。
I've been a fan of constructor injection for as long as I've known about DI, because to my mind that's what a constructor is for. It states "I need instances of the following classes/interfaces in order to do my job" - e.g. pass me a
File
and anPrintWriter
and I'll write the contents of the former to the latter.And of course, this means that the code isn't aware of the DI framework, since the class is just being constructed with its required dependencies passed in. Additionally, I don't see the need for factories in this scenario, since the class is its own factory via the constructor.
As for the scenario you've identified in the second paragraph, I'm not sure if that's strictly related to dependency injection, but simply the design of the class hierarchy and responsibilities. Either your class knows specifically how to create an
Event
that corresponds to e.g. a failed login, in which case it does so (i.e. by calling the class' constructor); or, it doesn't know how to, in which case it will have to delegate to some kind of factory to create theEvent
.And in this case you could set up your class to use the same factory to create all ten events (define an
EventFactory
interface with 10 methods), or you could define a separate factory interface (& implementation) for each type of event that needs contructing. In this latter case you'd also need to pass in ten different factories in your main class' constructor.But again - this isn't anything to do with DI IMHO, it's a question of how you design your classes for flexibility (or "enterprise-ness") vs. straightforwardness. The two are orthogonal, in my thinking; you first define what collaborators your class needs (ten factories, one factory, or zero factories) and then you use DI to provide those dependencies. The presence or otherwise of DI shouldn't impact on your class design.
一个类实例化许多其他对象并没有什么问题。相反,该类应被视为聚合根域实体。对于不同“类型”的实体,如果假设它们实现相同的接口或继承自相同的基类,则将
type
参数传递给Factory.create(type)
这是我通常处理这个问题的方式。 create() 的内部结构可以将策略模式委托给其他类,但面向客户端的 API 很简单。现在,如果您为正在处理的每个类创建一个工厂,这听起来像是反模式。研究上面提到的聚合根模式,看看您是否可以将实体组织成图表(您应该能够),这样一个工厂就足以生成整个图表。
对于 IoC,领域模型不应该知道容器。当我有需要引用容器中的单例(通常是工厂)的实体时,我通常将一个工厂注入另一个工厂:
因此在上面的示例中
FactoryA
和FactoryB
都是由 IoC 容器管理的单例。 EntityA 需要对FactoryB
的引用,因此FactoryA
注入了对FactoryB
的引用,该引用在create()方法。
There's nothing wrong with a class that instantiates many other objects. Instead, that class should be treated as an aggregate root domain entity. As for different "types" of entity, if you assume they implement the same interface or inherit from the same base class, then passing a
type
argument toFactory.create(type)
is how I usually go about approaching this issue. The internals ofcreate()
may delegate to other classes ala the Strategy pattern, but the client facing API is straightforward.Now if you're creating a factory for every class you're dealing with, that sounds like something of anti-pattern. Study the aggregate root pattern mentioned above and see if you can organize your entities into graphs - you should be able to - such that one factory suffices for generating the whole graph.
As for IoC, the domain model should not know about the container. When I have entities that need references to singletons - usually factories - in the container I usually inject one factory into another as such:
So in the above example both
FactoryA
andFactoryB
are singletons managed by the IoC container. EntityA needs a reference toFactoryB
, soFactoryA
is injected with a reference toFactoryB
that's passed along inside thecreate()
method.