3

レシピアプリケーションのドメインモデルに取り組んでいて、問題が発生しています。

アプリケーションには、材料として機能できる複数のエンティティがあり、そのうちの2つは次のとおりです。ProductおよびRecipe(レシピは他のレシピの材料にすることができます)。通常、私はこれらの各エンティティが実装できるインターフェースに成分関連の機能をカプセル化します。問題は、すべての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
    }
}

一部のレシピインスタンスのみが材料として機能できる必要があるという要件をサポートするために、このモデルを再構築するにはどうすればよいですか?

4

6 に答える 6

2

私にはデザインの問題のように聞こえます。IsIngredientのテストを開始する必要がある場合は、設計が間違っていると思います。別の特別な場合の条件があるとどうなりますか?そして別の?特別なIfテストまたは大きなswitchステートメントを追加し続けるつもりですか?それは開放閉鎖原則を破ります。

継承よりもコンポジションを優先するのはどうですか?戦略パターンも確認することをお勧めします...

ここでの中心的な問題は、レシピがIIngredientを実装してはならないということです...すべてのレシピがIIngredientの動作を実装しているわけではないからです...

于 2012-04-25T23:30:23.157 に答える
2

クラスツリーで機能する場合は、これら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 に答える
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

You could use an adaptor to make a recipe behave as an ingredient:

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 に答える