Question

Ceci est principalement une expérience de pensée. Donc, tout cela est un exemple de code. Mon objectif était d'utiliser le modèle de spécification pour éliminer les blocs géants de code conditionnel dans une usine. Donc, avec cet exemple que j'ai un objet StatusData que je veux obtenir une mise en œuvre de IStatusUpdate qui est approprié pour pour elle.

Je l'ensemble des tests suivants:

    [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));
    }

Ma mise en œuvre de l'usine a l'air si loin comme ceci:

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;

    }
  }

Là où je suis en train de tomber vers le bas est une fois que je l'ai découvert une spécification qui est satisfaite par l'objet d'état, comment puis-je mapper cette spécification à un type qui implémente IStatusUpdate .. Je suis perplexe.

Quelqu'un suggéré à juste titre que je besoin d'une cartographie des spécifications IStatusUpdate implémenteurs. Cette cartographie semble être une responsabilité de l'usine, l'accrocher au large de la spécification sent comme une violation du SRP. Je pourrais créer une classe Mapper qui a cette responsabilité, mais cela ne semble pas très générique et soulève aussi la question de savoir comment puis-je mapper le cartographe à la spécification.

Il y a encore un petit saut ici, je suis absent.

Était-ce utile?

La solution

Je suppose donc que nous nous concentrons vraiment sur cet ensemble de lignes:

if (spec.IsSatisfiedBy(item))
          return new NewStatusUpdate();

et je suppose que vous vous demandez comment sous cette forme actuelle, cela peut être fait. Il semble que l'article devrait soutenir comme

interface ISpecSupport<T>
{
    bool ItemSpecsContain(ISpecification<T> spec);
}

Ensuite, la méthode spec.IsSatisfiedBy peut prendre dans ce type d'interface et exécuter la méthode.

En d'autres termes, je suppose que je dis que l'objet doit porter une sorte de description de ce qu'elle est (en termes de spécifications). Je devine que c'est une liste de quelque sorte, mais je ne suis pas sûr. Je suis sûr que vous avez probablement pensé, donc si vous pouvez ajouter quelque chose qui serait utile.

En outre, au lieu de ce qui précède, vous pourriez peut-être réorganiser comme ceci:

if (item.Satisfies(spec))
    return new NewStatusUpdate();

Alors cette façon, vous ne devez pas utiliser le modèle des visiteurs beaucoup décrié (je pense que ce que je décrivais avant cela). Il est plus direct depuis l'élément semble comme il serait propriétaire des spécifications et de cette façon vous permettez la question de décider si elle répond à la spécification.

Si vous ne voulez pas cette logique a eu lieu dans l'objet (que je comprendrais) et que vous utilisez un sac de propriété de quelque sorte (ou que vous êtes cool avec la réflexion), vous pouvez creuser dans les détails de l'objet avec un validateur de spécification indépendante. En fait, un validateur indépendant pourrait ne pas être une mauvaise idée de commencer. Je ne suis pas si sûr que la capacité de savoir si une spécification correspond à un élément est une responsabilité qui doit rester avec une spécification individuelle.

Autres conseils

Si je comprends bien, vous voulez, étant donné un objet implémentant ISpecification vous voulez un objet qui implémente IStatusUpdate?

Dans votre échantillon aucun de ces types sont définis, donc je ne sais pas s'il existe une relation entre eux, vous pouvez utiliser.

Mais probablement, vous aurez soit besoin d'une usine pour maintenir le code, ou une méthode ISpecification.GetUpdate () pour la création d'objets.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top