3

我正在研究配方应用程序的域模型并遇到问题。

该应用程序具有多个能够充当成分的实体,其中两个是:ProductRecipe(配方可以是其他配方中的成分)。通常,我会将与成分相关的功能封装到每个实体都可以实现的接口中。问题是,虽然所有 Product 实例都可以是成分,但只有一部分 Recipe 实例可以是成分

interface IIngredient
{
    void DoIngredientStuff();
}

class Product : IIngredient
{
    void DoIngredientStuff()
    {
        // all Products are ingredients - do ingredient stuff at will
    }
}

class Recipe : IIngredient
{
    public IEnumerable<IIngredient> Ingredients { get; set; }

    void DoIngredientStuff()
    {
        // not all Recipes are ingredients - this might be an illegal call
    }
}

我如何重构这个模型来支持只有一些Recipe 实例才能充当成分的要求?

4

6 回答 6

2

如果它在您的类树中为这两种类型的食谱具有单独的类,则另一种选择。请注意,如果您要区分对象的属性更多,则此方法效果不佳。

class Recipe {
    public IEnumerable<IIngredient> Ingredients { get; set; }

}

class UsefulRecipe : Recipe, IIngredient
{
    void DoIngredientStuff()
    {
        // not all Recipes are ingredients - this might be an illegal call
    }
}
于 2012-04-25T23:31:04.060 回答
2

对我来说听起来像是一个设计问题。如果您必须开始为 IsIngredient 进行测试,我认为您的设计出了问题。当您遇到另一个特殊情况时会发生什么?然后另一个?你会继续添加特殊的 If 测试或大的 switch 语句吗?这打破了开闭原则。

喜欢组合而不是继承怎么样?您可能还想查看策略模式...

这里真正的核心问题是Recipe不应该实现IIngredient ...因为并非所有Recipe都实现IIngredient行为...

于 2012-04-25T23:30:23.157 回答
1
interface IIngredient 
{ 
    bool IsIngredient { get; }
    void DoIngredientStuff(); 
} 

class Recipe : IIngredient 
{ 
    public IEnumerable<IIngredient> Ingredients { get; set; } 

    bool IsIngredient {
       get { return true; // true if it is, false if it isn't }
    }   

    void DoIngredientStuff() 
    { 
      if (IsIngredient) {
        // do whatever
      }
    } 
} 
于 2012-04-25T23:23:03.413 回答
0

我可能会使用组合来创建一个CompositeRecipe可以组合 2 个(也许更多)食谱的。没有所有食谱都可以用作新食谱的基础的原因是什么?您始终可以添加一个布尔属性来表明该配方是一个完整的配方 ( IsCompleteRecipe),然后取决于您如何构建应用程序和应用程序逻辑来确定该配方是否应该与其他配方组合。

于 2012-04-26T07:58:34.983 回答
0

如果只有一些食谱是成分,那么它似乎是继承的经典案例,IIngredient在子类上实现:

class Product : IIngredient
{
    void DoIngredientStuff();
}

class Recipe
{
    public IEnumerable<IIngredient> Ingredients { get; set; }
}

class IngredientRecipe : Recipe, IIngredient
{
    void DoIngredientStuff();
}
于 2012-04-27T02:15:19.103 回答
-1

您可以使用适配器使配方表现为成分:

class RecipeIngredient : IIngredient
{
    private readonly Recipe _recipe;

    public RecipeIngredient(Recipe recipe) {
        _recipe = recipe;
    }

    public void DoIngredientStuff() {
        // Do stuff with the recipe.
    }
}
于 2012-04-26T00:41:57.523 回答