Architecture 域对象中服务的有条件使用

Architecture 域对象中服务的有条件使用,architecture,inversion-of-control,dependencies,Architecture,Inversion Of Control,Dependencies,因此,假设我的三明治店有两个服务接口,IMeatGetter和ivegiesgetter。现在我有了一个域对象,Sandwich,它的属性是素食主义者。我想要一个方法来选择所有可能的浇头,比如 void GetToppings { if IsVegetarian select (veggies) else select (veggies union meats) } 将服务传递给三明治构造函数是正确的域设计吗?或者,在更高的层次上,你会先把肉和蔬菜装进去,然后把它们都传

因此,假设我的三明治店有两个服务接口,IMeatGetter和ivegiesgetter。现在我有了一个域对象,Sandwich,它的属性是素食主义者。我想要一个方法来选择所有可能的浇头,比如

void GetToppings
{
  if IsVegetarian
    select (veggies)
  else
    select (veggies union meats)
}
将服务传递给三明治构造函数是正确的域设计吗?或者,在更高的层次上,你会先把肉和蔬菜装进去,然后把它们都传给三明治吗


如果IMeatGetter是一个非常慢的操作怎么办?这会改变你的答案吗?

与此相关的一个学派认为域对象应该是POCOs/POJO,因此根据这一理念,夹心阶层应该独立于IMeatGetter和IVegiesgetter服务。我个人发现,尽管存在某些缺点,但这种方法仍然很有效

如果蔬菜和肉类的总清单在三明治的上下文中有意义,那么对我来说它更像是一个潜在的三明治,不过,我会将它们作为构造器的一部分传递进来。下面是一个C示例:

public class Sandwich
{
    private readonly IEnumerable<Ingredient> veggies;
    private readonly IEnumerable<Ingredient> meats;

    public Sandwich(IEnumerable<Ingredient> veggies, IEnumerable<Ingredient> meats)
    {
        if(veggies == null)
        {
            throw new ArgumentNullException("veggies");
        }
        if(meats == null)
        {
            throw new ArgumentNullException("meats");
        }

        this.veggies = veggies;
        this.meats = meats;
    }

    // implement GetToppings as described in OP
}
如果使用IMeatGetter检索肉类列表,这是一个非常缓慢的操作,那么不,这不会改变我的答案。通过这种方式,我们将三明治阶层与肉类的检索逻辑分离

这使我们能够尝试管理其他地方肉类列表的生命周期。例如,我们可以编写一个IMeatGetter实现,在内存中缓存肉类列表

即使这是不可能的,我们仍然可以更改列表本身以进行延迟评估。虽然我不知道您使用的是哪个平台,但在.NET中,IEnumerable接口允许延迟执行;换句话说,在您真正开始枚举之前,它不会检索列表

若您在另一个平台上工作,那个么引入一个支持延迟加载肉类的自定义接口应该还是很简单的

总之,您将对列表的引用传递到三明治类中。那个列表可能会也可能不会在那个时候被载入内存,但这取决于你们的控制——独立于夹心阶层。因此,夹心阶层符合单一责任原则,因为他们不必管理肉类的寿命