如何将依赖注入应用于抽象工厂

sha*_*p00 5 c# dependency-injection

我刚刚完成了Mark Seemann的书籍Dependency Injection in .NET,现在我正在尝试重构一些遗留代码.(在此阶段,我不依赖于任何特定的DI容器,而只是尝试将所有依赖项移动到一个位置).

我正在查看以下工厂类,它ArchiveType通过读取存档的前几个字节来确定archiveReader.GetArchiveType(),然后返回ArchiveRestorer基于ArchiveType枚举的实例.

public class ArchiveRestorerFactory : IArchiveRestorerFactory
{
    public ArchiveRestorer Create(ArchiveReader archiveReader)
    {
        ArchiveType type = archiveReader.GetArchiveType();
        switch (type)
        {
            case ArchiveType.CurrentData:
                return new CurrentDataArchiveRestorer(archiveReader);
                break;
            case ArchiveType.HistoricalData:
                return new HistoricalDataArchiveRestorer(archiveReader);
                break;
            case ArchiveType.AuditTrail:
                return new AuditTrailArchiveRestorer(archiveReader);
                break;
            default:
                throw new Exception("ArchiveRestorerFactory error: Unknown value for ArchiveType.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我如何重构这个,以便该类不依赖于具体的类型CurrentDataArchiveRestorer,HistoricalDataArchiveRestorer并且AuditTrailArchiveRestorer

我应该将三个具体的恢复器移动到工厂的构造函数中吗?

public ArchiveRestorer Create(ArchiveReader archiveReader, 
    ArchiveRestorer currentDataArchiveRestorer, 
    ArchiveRestorer historicalDataArchiveRestorer, 
    ArchiveRestorer auditTrailDataArchiveRestorer)
{
    // guard clauses...
    // assign to readonly fields
}
Run Code Online (Sandbox Code Playgroud)

这似乎是这里建议的方法,但是当只需要一个时,它将实例化所有三个恢复器?如果我有20种不同的具体实现呢?

我觉得我应该为每种类型的恢复器实现一个具体的工厂并返回它,但后来我只是将它们替换new为另一个.

重构这个的最佳方法是什么?

Jam*_*xon 2

考虑到您已经获得的代码,我执行此操作的方法是为每个具有方法的对象创建一个工厂Create()

我也有这些工厂的接口,并让它们继承通用工厂接口。

然后,您可以使用这些接口作为注入构造函数的点。

这将被称为类似于:

case ArchiveType.CurrentData:
                return _currentDateArchiveRestorerFactory.Create(archiveReader);
                break;
Run Code Online (Sandbox Code Playgroud)

或者,最好有一个工厂来创建给定类型的实例。由于所有这些对象都是恢复器,因此您可以仅基于enum而不是基于switch.

_restorerFactory.Create(ArchiveType.CurrentData);
Run Code Online (Sandbox Code Playgroud)