1

ここに投稿された質問を参照して、これが継承ではなく構成を使用してクラスを拡張するためのオプションの動作を解決するための良いアプローチであるかどうかコメントしてください。Plannableここでは、動作はストラテジーパターンによって拡張されます。

したがって、クラスTaskはオプションでさまざまな動作の任意の組み合わせを持つことができます。Plannableはそのうちの1つにすぎないため、ここでは継承は明らかに意味がありません。

質問は、タスクに特定の動作がない場合にどうするかです。考えられるアプローチはほとんどありません。

  1. Task各タスクの具体的な戦略をインスタンス化し、そうでない場合は「ダミー」戦略を実装しますPlannable(この代替案を以下に示します)。この場合、コード全体に奇妙なnull許容型Startと変数があります...Finish
  2. ケースタスクでIPlanningStrategynullable変数を使用することは計画されておらず、具体的なStrategyが「プロモート」されている場合にのみインスタンス化されますPlannable

代替案(1)は次のようになります。

public class Task
{
    public string Title { get; set; }

    private IPlanningStrategy planningStrategy;

    public Task()
    {
        planningStrategy = new NoPlanStrategy();
    }

    public Task(IPlanningStrategy initialPlanningStrategy)
    {
        planningStrategy = initialPlanningStrategy;
    }

    public void SetPlanningStrategy(IPlanningStrategy newPlanningStrategy)
    {
        planningStrategy = newPlanningStrategy;
    }

    public DateTime? Start { get { return planningStrategy.Start; } }
    public DateTime? Finish { get { return planningStrategy.Finish; } }
}


public interface IPlanningStrategy
{
    public void CalculatePlan();
    public DateTime? Start { get; }
    public DateTime? Finish { get; }
}

// "Dummy" strategy, used when Task does not have Planning behaviour
//
public class NoPlanStrategy : IPlanningStrategy
{
    public void CalculatePlan() { }
    public DateTime? Start { get { return null; } }
    public DateTime? Finish { get { return null; } }
}



public class PlanStrategyA : IPlanningStrategy
{
    private int parameter1;
    private int parameter2;
    private DateTime? start;
    private DateTime? finish;

    public PlanStrategyA(int p1, int p2)
    {
        parameter1 = p1;
        parameter2 = p2;
        start = finish = null;
    }

    public void CalculatePlan()
    {
        // ... uses parameter1 & parameter2
        // ... to calculate start and finish
    }

    public DateTime? Start { get { return start; } }

    public DateTime? Finish { get { return finish; } }
}

public class PlanStrategyB : IPlanningStrategy
{
    public int parameter3;

    // ... the rest is similar to PlanningStrategyA

}

ここで、さまざまな**非常に重要**な問題が発生します。私の具体的なStrategyクラスのそれぞれは、アルゴリズムのほかに、このアルゴリズムを実装するすべてのタスクで共有される、特定のにのみ属する追加のパラメーターを保持しますTask

parameter1次のように想像できますEffort(または、たとえば、タスクを完了するために必要な残り時間数)、および(制約日、つまりparameter2LastDateタスクを完了するための最後の許容日を表す)と言うことができます。このパラメータは当然特定のものに属しますTaskが、この特定のものを実装している場合に限りStrategyAます。

クラス外のインスタンス化戦略Taskは意味がないようですか?または、これはいくつかの方法の仕事である必要がありFactoryますか?

4

1 に答える 1

0

TaskIMOあなたはあなたのクラスであまりにも多くの情報を公開しています。私は次のようにします:

public class Task
{
    // what is title being used for?
    public string Title { get; set; }

    private IPlanningStrategy planningStrategy;

    public Task(IPlanningStrategy initialPlanningStrategy)
    {
        // Initialize it outside of constructor
        if(initialPlanningStrategy == null)
        {  
           throw new NullArgumentException(); // or return. 
        }
        planningStrategy = initialPlanningStrategy;
    }

    public void CalculatePlan(){
        // check null and return.
        planningStrategy.CalculatePlan();
    }

}

あなたのクライアントは開始、終了を知っているべきではありません、私はそれをアルゴリズムのコンテナの責任として見ていません。

さらに、NoPlanStrategyが何もしていない場合は、なぜそれを導入するのですか。それを除く。

于 2012-11-22T00:37:45.743 に答える