How to restrict specific behavior to a subset of instances of a particular class?

I am working on a domain model for a recipe application and am facing a problem.

The application has several objects that can act as an ingredient, two of which are: Productand Recipe(recipes can be ingredients in other recipes). I usually encapsulated the functionality associated with the ingredient in an interface that each of these objects could implement. The problem is that although all instances of a product can be ingredients , only a subset of instances of a recipe can be an ingredient .

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
    }
}

How can I restructure this model to support the requirement that only certain instances of the Recipe act as an ingredient?

+3
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
    }
}
+2

. IsIngredient, , . , ? ? If switch? Open-Closed.

? ...

, IIngredient... IIngredient...

+2
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
      }
    } 
} 
+1

, CompositeRecipe, 2 (, ) . , ? boolean, , (IsCompleteRecipe), , , , .

0

, , IIngredient :

class Product : IIngredient
{
    void DoIngredientStuff();
}

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

class IngredientRecipe : Recipe, IIngredient
{
    void DoIngredientStuff();
}
0

You can use an adapter to make the recipe behave like an ingredient:

class RecipeIngredient : IIngredient
{
    private readonly Recipe _recipe;

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

    public void DoIngredientStuff() {
        // Do stuff with the recipe.
    }
}
-1
source

All Articles