这完全取决于您将工厂放在哪里以及您对每个工厂承担多少责任。例如,如果您有以下工厂
' In the data access layer project
Public Class DataAccessFactory()
Implements IDataAccessFactory
Public Sub New()
' ...
End Sub
' ...
End Class
' In the business layer project
Public Class BusinessFactory()
Public Sub New(daFactory As IDataAccessFactory)
' ...
End Sub
' ...
End Class
现在,当您在 UI 中创建业务工厂时,您首先必须在 UI 层创建一个数据访问工厂,以便您可以将其注入业务工厂。因此,在这种情况下,UI 层需要同时引用业务和数据访问层项目。但是,你也可以给业务工厂更多的责任,像这样:
Public Class BusinessFactory()
Public Sub New()
_daFactory = New DataAccessFactory()
End Sub
Private _daFactory As IDataAccessFactory
' ...
End Class
现在,UI 层无法决定将使用哪个数据访问层,但它也不再需要对数据访问层项目的引用。在第二个示例中,只有业务层项目需要对数据访问层项目的引用。
它不太灵活,因为您需要为要支持的每个数据访问工厂实现一个单独的业务工厂,但是您可以通过如下方式实现它来使其更加灵活:
Public Class BusinessFactory()
Implements IBusinessFactory
Public Sub New()
_daFactory = NewDataAccessFactory()
End Sub
Private _daFactory As IDataAccessFactory
Protected Overridable Function NewDataAccessFactory() As IDataAccessFactory
Return New DataAccessFactory()
End Function
' ...
End Class
请注意,该NewDataAccessFactory
方法是可覆盖的。所以现在,当您需要使用不同的数据访问工厂时,您可以覆盖相同的方法,而无需复制工厂逻辑的其余部分。例如:
Public Class XmlBusinessFactory()
Inherits BusinessFactory
Public Sub New()
MyBase.New()
End Sub
Protected Overridable Function NewDataAccessFactory() As IDataAccessFactory
Return New XmlDataAccessFactory()
End Function
End Class
当然,所有逻辑(非工厂)类仍然是完全可注入的。只有工厂类的灵活性稍差。但是,从好的方面来说,您的 UI 层不仅不再需要引用数据访问层,而且还使您的工厂对象的实例化变得更加容易。您需要做的就是创建您需要的工厂,而不是创建它的所有依赖工厂。
如果您需要使工厂的依赖项可注入,例如对工厂进行单元测试,您仍然可以通过创建可注入的派生类来实现,如下所示:
Public Class InjectableBusinessFactory()
Inherits BusinessFactory
Public Sub New(daFactory As IDataAccessFactory)
MyBase.New()
_daFactory = daFactory
End Sub
Private _daFactory As IDataAccessFactory
Protected Overridable Function NewDataAccessFactory() As IDataAccessFactory
Return _daFactory
End Function
End Class
所以,虽然这样做需要额外的步骤,但这确实意味着遵循这个设计并不意味着你把自己画到一个角落里。最后,您需要权衡利弊并选择最适合您的情况。我建议尝试以两种方式实现您的工厂,以便您对这两种方法都有感觉。