I’ve just finished Mark Seemann’s book Dependency Injection in .NET and I’m now trying to refactor some legacy code. (I am not, at this stage, relying on any particular DI container, rather just trying to move all the dependencies to one place).
I’m looking at the following factory class which determines the ArchiveType by reading the first few bytes of the archive with archiveReader.GetArchiveType() and then returns an instance of an ArchiveRestorer based on the ArchiveType enum.
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.");
}
}
}
How do I refactor this so that the class does not depend on the concrete types CurrentDataArchiveRestorer, HistoricalDataArchiveRestorer and AuditTrailArchiveRestorer?
Should I move the three concrete restorers into the factory’s constructor?
public ArchiveRestorer Create(ArchiveReader archiveReader,
ArchiveRestorer currentDataArchiveRestorer,
ArchiveRestorer historicalDataArchiveRestorer,
ArchiveRestorer auditTrailDataArchiveRestorer)
{
// guard clauses...
// assign to readonly fields
}
That seems to be the approach suggested here, but then it will instantiate all three restorers when only one is needed? What if I had 20 different possible concrete implementations instead?
I feel like I should be implementing a concrete factory for each type of restorer and returning that instead but then I would just be replacing one new with another.
What is the best way to refactor this?
The way I’d do this, given the code you’ve already got, would be to create a factory for each of these objects which has a
Create()method.I’d have an interface for these factories also and have them inherit from a general factory interface.
You can then use the interfaces as a point for injection into your constructor.
Which would be called similar to this:
Alternatively, it might be better to have a single factory that creates an instance of a given type. Since all of these objects are restorers you could just create the instance based on the
enumrather than aswitch.