Pregunta

Esto es principalmente un experimento mental. Así que todo esto es código de ejemplo. Mi objetivo era utilizar el patrón de especificación para eliminar gigantescos bloques de código condicional dentro de una fábrica. Así que con esta muestra Tengo un objeto StatusData que quiero conseguir una implementación de IStatusUpdate que es apropiado para por ello.

Tengo el siguiente conjunto de pruebas:

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

Mi aplicación de la fábrica hasta el momento es el siguiente:

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;

    }
  }

¿Dónde estoy cayendo hacia abajo es una vez que he descubierto una especificación que se satisface con el objeto de estado, ¿cómo Mapa esa especificación de un tipo que implementa IStatusUpdate .. Estoy confundido.

Alguien sugirió con razón que necesito un mapeo de las especificaciones a los ejecutores IStatusUpdate. Esta correlación parece ser una responsabilidad de la fábrica, colgando fuera de la especificación huele como una violación de la SRP. Podría crear una clase Mapper que tiene esa responsabilidad, pero eso no parece muy genérico y también plantea la pregunta ¿Cómo puedo asignar el asignador de la especificación.

Hay todavía un pequeño salto aquí me falta.

¿Fue útil?

Solución

Así que estoy asumiendo que estamos muy centrados en este conjunto de líneas:

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

y supongo que estás preguntando cómo en esta forma actual esto se puede hacer. Parece como elemento debe apoyar como

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

A continuación, el método spec.IsSatisfiedBy puede tomar en este tipo de interfaz y ejecutar el método.

En otras palabras, supongo que estoy diciendo que el objeto debe realizar algún tipo de descripción de lo que es (en términos de especificaciones). Supongo que eso es una lista de algún tipo, pero no estoy seguro. Estoy seguro de que probablemente ha pensado de esta manera si se puede añadir cualquier cosa que estaría muy útil.

Además, en lugar de lo anterior tal vez usted podría reorganizar este modo:

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

A continuación, de esta manera usted no tiene que utilizar el modelo mucho difamado visitante (creo que eso es lo que yo estaba describiendo antes de esto). Es más directa desde el elemento parece que será la propietaria de las especificaciones y de esta manera se va a permitir el elemento para decidir si cumple con la especificación.

Si no desea que esta lógica se celebró dentro del objeto (que yo entendería) y está utilizando una bolsa de una especie de propiedad (o que está fresco con la reflexión) se podría profundizar en los detalles del objeto con un validador de especificación independiente. En realidad, el validador independiente que podría no ser una mala idea para empezar. No estoy tan seguro de que la capacidad de saber si una especificación corresponde con una partida es una responsabilidad que debe permanecer con una especificación individual.

Otros consejos

Si no he entendido mal, usted quiere, dado un objeto que implementa ISpecification desea un objeto que implementa IStatusUpdate?

Se definen su muestra ninguno de estos tipos, por lo que no sé si hay alguna relación entre ellos se podía utilizar.

Pero probable es que sea necesario necesitar algo de fábrica para mantener el código, o una ISpecification.GetUpdate () para hacer la creación del objeto.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top