3

这主要是一个思想实验。所以这一切都是示例代码。我的目标是使用规范模式来消除工厂内大量的条件代码。因此,对于这个示例,我有一个 StatusData 对象,我想获得一个适合它的 IStatusUpdate 实现。

我有以下一组测试:

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

到目前为止,我的工厂实现如下所示:

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;

    }
  }

一旦我发现了状态对象满足的规范,我就会失败,我如何将该规范映射到实现 IStatusUpdate 的类型。我很难过。

有人正确地建议我需要将规范映射到 IStatusUpdate 实现者。这种映射似乎是工厂的责任,把它挂在规范之外闻起来像是违反了 SRP。我可以创建一个具有该职责的 Mapper 类,但这似乎不是很通用,并且还提出了如何将映射器映射到规范的问题。

我在这里仍然缺少一个小飞跃。

4

2 回答 2

3

如果我理解正确,你想要,给定一个实现 ISpecification 的对象,你想要一个实现 IStatusUpdate 的对象吗?

在您的示例中,这些类型均未定义,因此我不知道您可以使用它们之间是否存在任何关系。

但是您可能需要一些工厂来保存代码,或者需要一个 ISpecification.GetUpdate() 方法来创建对象。

于 2009-02-20T00:46:30.350 回答
1

所以我假设我们真的专注于这组线:

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

我假设你问的是如何以目前的形式做到这一点。似乎项目应该支持

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

然后 spec.IsSatisfiedBy 方法可以接受这个接口类型并运行该方法。

换句话说,我想我是说该对象应该对它的内容进行某种描述(就规格而言)。我猜这是某种列表,但我不确定。我相信你可能已经想到了这一点,所以如果你能添加任何有用的东西。

此外,您可以像这样重新排列它,而不是上面的:

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

这样,您就不必使用备受诟病的访问者模式(我认为这就是我之前所描述的)。它更直接,因为该项目似乎拥有规范,这样您就允许该项目决定它是否符合规范。

如果您不希望将此逻辑保存在对象中(我会理解)并且您正在使用某种属性包(或者您对反射很酷),您可以使用独立规范深入了解对象的细节验证器。实际上,一个独立的验证者一开始可能不是一个坏主意。我不太确定知道规格是否与项目匹配的能力是否应该由单个规格保留。

于 2009-02-20T00:58:49.383 回答