转移 IDisposable 对象的所有权和构建器设计模式

Transferring ownership of an IDisposable object and the builder design pattern

当对象创建另一个对象(直接或通过工厂、构建器等)时,我习惯了这种方法 - 是 "owns" 它的对象,从而管理它的生命周期。

这个想法几乎适用于所有情况。

但有时创建对象的人根本无法管理它,例如在构建器设计模式实现中:

IFoo BuildFoo()
{
    var dep = new Dep();

    return new Foo(dep);
}

因此,此处构建器无法管理 dep 对象的生命周期,因为:

  1. 它没有对它的引用;
  2. 它不知道什么时候Dispose它是安全的。

天真的解决方案是制作 Foo : IDisposable 并让它管理传递给其构造函数的 Dep

但另一个难题出现了:

using (var dep = new Dep())
{
    using (var foo = new Foo(dep))
    {
        // (1) do something with foo
    }

    // (2) !!! do something with dep !!!
}

上面的代码变得不安全:在(2)点使用dep是不安全的,因为它已经被foo.Disposed了。

而且在句法上没有任何东西可以表示,它的职责是管理对象的生命周期。

所以问题是:什么是通用解决方案?

你让 Foo 调用构建器来实例化 Dep 并在需要时使用它呢?这样 Foo 管理 Dep 的生命周期,而 Foo 的客户端不必担心它。

非常幼稚的实现

void Main()
{
    using (var builder = new Builder())
    {
        var foo = builder.Create();
        // do smtg
    }
}

public class Foo
{
    public Foo(Dep instance)
    {
    }
}

public class Dep : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine($"{this.GetType().Name} disposed!");
    }
}

public class Builder : IDisposable
{
    private List<IDisposable> _disposables = new List<System.IDisposable>();

    public Foo Create()
    {
        var dep = new Dep();
        _disposables.Add(dep);

        var foo = new Foo(dep);
        return foo;
    }

    public void Dispose()
    {
        foreach(var d in _disposables)
            d.Dispose();

        Console.WriteLine($"{this.GetType().Name} disposed!");
    }
}

如果某物拥有 IDisposable,那么它应该实现 IDisposable。 而且,当然,这是非常幼稚的实现,就像示例一样。

在这种情况下,我不会担心。我想我会在这里被打成碎片,但是 "builders"、"factories" 等都是我认为可以创建对象并将其处理交给请求的对象的地方它。

虽然有一条规则,但 builder/factory 必须 创建 对象,而不对它做任何事情.

当然,如果您使用 new 关键字更新对象,那么您就是在将自己耦合到该实现(即使它是通过工厂 class 间接实现的)。您可能想要考虑依赖注入,具体取决于创建的对象的用途,在这种情况下,DI 容器将创建对象 and 在正确的时间为您处理它们,基于他们配置的生活方式。