【问题标题】:Factory which creates disposable objects制造一次性物品的工厂
【发布时间】:2022-01-04 11:09:39
【问题描述】:

假设我有一个基于一次性资源创建服务的工厂。 我认为第一个解决方案是最干净的,但我无法弄清楚如何在我的情况下处理“实例”。 第二个将是一个解决方案,但可以称为工厂吗?我不这么认为,因为它拥有适当的资源。 此外,“DisposableIOResource”是一种很难创建的服务,您只想躲在工厂后面。 有解决这种情况的好模式吗? 在我的两个草稿 sn-ps 下方。

// first solution
public class ServiceFactory
{
    public Reader CreateReader(string configuration) 
    {
        var instance = new  DisposableIOResource(configuration);
        return new Reader(instance);
    }
}

// first solution - use case
var serviceFactory = new ServiceFactory();
var reader = serviceFactory.CreateReader(configuration)
reader.DoSomething(); // NOTE! How do I dispose 'instance'???


// second solution
public class ServiceFactory : IDisposable
{
    private readonly DisposableIOResource _instance;

    public ServiceFactory(string configuration)
    {
        _instance = new  DisposableIOResource(configuration);
    }

    public Reader CreateReader() 
    {
        return new Reader(_instance);
    }

    public void Dispose()
    {
        _instance.Dispose();
    }
}

// second solution - use case
using(var serviceFactory = new ServiceFactory(configuration))
{
    var reader = serviceFactory.CreateReader():
    reader.DoSomething();
}

--- 编辑 我最终找到了另一种解决方案,也许是更清洁的解决方案:


public interface IDisposableIOResourceFactory
{
    DisposableIOResource Create();
}

public class DisposableIOResourceFactory : IDisposableIOResourceFactory
{
    private readonly string _configuration;
    public DisposableIOResourceFactory(string configuration) 
    {
       _configuration = configuration;
    }

    public DisposableIOResource Create()
    {
        return new  DisposableIOResource(this._configuration);
    }
}

// third solution

public class ServiceFactory
{
    public Reader CreateReader(IDisposableIOResourceFactory resourceFactory) 
    {
        return new Reader(resourceFactory);
    }
}

public class Reader
{
   public Reader(IDisposableIOResourceFactory resourceFactory) {}

   public void DoSomething()
   {
      using var resource = resourceFactory.Create();
      // work on resource
   }
}

// first solution - use case
var serviceFactory = new ServiceFactory();
var resourceFactory = new DisposableIOResourceFactory();
var reader = serviceFactory.CreateReader(resourceFactory);
reader.DoSomething();

【问题讨论】:

  • 在我看来,Reader 类应该实现 IDisposable。你想达到什么目的?
  • 两者在技术上都是工厂,但您的第二个实现使用通常与工厂不重合的单例模式。我不会过多关注标签,而是代码为您做了什么,以及它解决了哪些问题。
  • using var reader = serviceFactory.CreateReader(configuration); 然后Reader 负责处理它的任何内部资源。
  • 工厂无法猜测消费者何时使用完对象。因此,它必须是实现 IDisposable 的 Reader 类。
  • @Zoidbergseasharp 让我深入探讨我的问题。只需将“阅读器”视为 DisposableIOResource 上的适配器,它确实可以帮助您阅读该资源。现在,工厂的最终用户不知道如何构建该资源,因此您不能只要求他创建 DisposableIOResource。在这种情况下,唯一知道如何创建它的是工厂,但在这种情况下,“你如何处理这个对象 Dispose”?

标签: c# factory disposable


【解决方案1】:

您的工厂不需要实现 IDisposable。您的阅读器可以。

没关系。

// first solution
public class ServiceFactory
{
    public Reader CreateReader(string configuration) 
    {
        var instance = new  DisposableIOResource(configuration);
        return new Reader(instance);
    }
}

你不包括Reader

但它应该实现 IDisposable

public class Reader : IDisposable
{
    private readonly DisposableIOResource _instance;

    // Code Here
    public Reader(DisposableIOResource instance) {
        _instance = instance;
    }

    public void Dispose() {
       _instance?.Dispose();
    }
}

然后,当您创建一个时,您将其放入 using 中

var serviceFactory = new ServiceFactory(configuration);

using(var reader = serviceFactory.CreateReader()) {
   reader.DoSomething();
}

【讨论】:

  • 这只是故事的一半,Reader 需要处置instance。另外,我建议使用自 C# 8 以来一直存在的更新的 using 语法
  • 我故意省略了 Reader 处理 instance 因为该代码未包含在原始问题中。但是,是的,这是正确的。同意,如果可能的话,使用更新的语法,但从问题中不清楚他使用的是什么语言版本,所以我选择了最兼容的。
  • @DavidG 这不是关于如何实现 IDisposable 的问题——SO 上已经有十亿个。 Kaddyuk 已经回答了核心问题。如果 OP 想了解实现,他可以搜索并找到。
  • @Ricibob 我很清楚这一点,但 OP 专门询问如何处理内部对象,而不是 Reader 对象。
  • 在 Reader 中实现了实例的 dispose。不需要添加空运算符?如果您启用了可空性,但包括在内是为了向后兼容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多