【发布时间】:2018-01-20 05:46:04
【问题描述】:
这个问题困扰了我很久,一直没有找到正确的答案。
问题。
假设您有一个工厂接口(C# 示例):
interface IFooFactory
{
IFoo Create();
}
它的实现依赖于服务:
class FooFactory : IFooFactory
{
private readonly IBarService _barService;
public FooFactory(IBarService barService)
{
_barService = barService;
}
}
服务接口实现IDisposable 以实现正常关闭:
interface IBarService : IDisposable
{
...
}
现在工厂创建的实际类有 2 个依赖项 - 服务本身(通过工厂传递),以及工厂创建的另一个对象:
class Foo : IFoo
{
public Foo(IBarService barService, IQux qux)
{
...
}
}
工厂可以像这样创建它:
class FooFactory : IFooFactory
{
public IFoo Create()
{
IQux qux = new Qux();
return new Foo(_barService, qux);
}
}
最后IFoo 和IQux 都实现了IDisposable,所以Foo 类实现了:
class Foo : IFoo
{
public void Dispose()
{
_qux.Dispose();
}
}
但是为什么我们只在Foo.Dispose() 上处理Qux?
这两个依赖项都是注入的,我们只依赖于工厂的确切实现知识,其中Bar 是共享服务(关联关系类型),Qux 仅由Foo 使用(组合关系类型)。错误地处理它们很容易。在这两种情况下,Foo 在逻辑上不拥有任何依赖项,因此处置它们中的任何一个似乎都是错误的。将Qux 的创建放在Foo 中会否定依赖注入,所以它不是一个选项。
有没有更好的方法来同时拥有这两种依赖关系,并明确它们需要什么样的关系才能正确处理它们的生命周期?
可能的解决方案。
所以这里有一个可能不是那么漂亮的解决方案:
class FooFactory : IFooFactory
{
private readonly IBarService _barService;
public FooFactory(IBarService barService)
{
_barService = barService;
}
public IFoo Create()
{
// This lambda can capture and use any input argument.
// Also creation can be complex and involve IO.
var quxFactory = () => new Qux();
return new Foo(_barService, quxFactory);
}
}
class Foo : IFoo
{
public Foo(IBarService barService, Func<IQux> quxFactory)
{
// Injected - don't own.
_barService = barService;
// Foo creates - Foo owns.
_qux = quxFactory();
}
public void Dispose()
{
// Now it's clear what Foo owns from the code in the constructor.
_qux.Dispose();
}
}
我不喜欢在构造函数中调用可能复杂的逻辑,特别是如果它是 async,并且按需调用(延迟加载)也可能导致意外的延迟运行时错误(与快速失败相比)。
仅仅为了设计而走那么远真的有意义吗?无论如何,我想看看是否有其他可能的优雅解决方案。
【问题讨论】:
标签: c# oop dependency-injection factory-pattern object-lifetime