Dies ist hauptsächlich ein Gedankenexperiment. Das alles ist also Beispielcode. Mein Ziel war es, das Spezifikationsmuster zu verwenden, um riesige Blöcke von bedingtem Code innerhalb einer Fabrik zu vermeiden. In diesem Beispiel habe ich also ein StatusData-Objekt, für das ich eine Implementierung von IStatusUpdate finden möchte, die für dieses Objekt geeignet ist.
Ich habe die folgende Reihe von Tests:
[TestMethod]
public void Factory_Interface_Should_Return_IStatusUpdate()
{
var factory = MockRepository.GenerateMock<IUpdateFactory<StatusData>>();
var obj = MockRepository.GenerateStub<IStatusUpdate>();
var data = new StatusData();
factory.Stub(x => x.Get(data)).Return(obj);
var item = factory.Get(data);
Assert.IsInstanceOfType(item, typeof(IStatusUpdate));
}
[TestMethod]
public void StatusUpdateFactory_Should_Return_IStatusUpdate()
{
var factory = new StatusUpdateFactory();
var data = new StatusData();
var item = factory.Get(data);
Assert.IsInstanceOfType(item, typeof(IStatusUpdate));
}
[TestMethod]
public void StatusUpdateFactory_Should_Return_NewStatusUpdate_When_Status_Is_New()
{
var data = new StatusData(Status.New);
var factory = new StatusUpdateFactory();
var item = factory.Get(data);
Assert.IsInstanceOfType(item, typeof(NewStatusUpdate));
}
Meine bisherige Implementierung von Factory sieht folgendermaßen aus:
public class StatusUpdateFactory:IUpdateFactory<StatusData>
{
public IStatusUpdate Get(StatusData item)
{
IList<ISpecification<StatusData>> specs = GetSpecifications();
foreach (var spec in specs)
{
if (spec.IsSatisfiedBy(item))
//how do I do this?
return new NewStatusUpdate();
}
return null;
}
private IList<ISpecification<StatusData>> GetSpecifications()
{
var returnList = new List<ISpecification<StatusData>>();
var specTypes = this.GetType().Assembly.GetTypes()
.Where(z => z.IsInstanceOfType(typeof(ISpecification<StatusData>)))
.ToList();
specTypes.ForEach(x => returnList.Add(Activator.CreateInstance(x) as ISpecification<StatusData>));
return returnList;
}
}
Wo ich falle ist, sobald ich eine Spezifikation entdeckt habe, die durch das Statusobjekt erfüllt ist, wie kann ich diese Spezifikation auf einen Typ, der IStatusUpdate implementiert abbilden. Ich bin verblüfft.
Jemand hat zu Recht vorgeschlagen, dass ich eine Zuordnung von Spezifikationen zu IStatusUpdate-Implementierern brauche. Diese Zuordnung scheint in der Verantwortung der Fabrik zu liegen, sie an die Spezifikation zu hängen, riecht nach einer Verletzung der SRP. Ich könnte eine Mapper-Klasse erstellen, die diese Verantwortung trägt, aber das scheint nicht sehr generisch zu sein und wirft auch die Frage auf, wie ich den Mapper auf die Spezifikation abbilde.
Es gibt noch einen kleinen Sprung, den ich übersehen habe.