參考發佈的問題here,請您評論一下,如果這是一個很好的方法來解決擴展類的可選行爲,那麼使用組合而不是繼承。 Plannable
行爲在這裏由策略模式擴展。具有虛擬混淆策略的策略模式
因此,類Task
可以可選地具有各種行爲的任意組合。 Plannable
只是其中之一,因此繼承在這裏顯然沒有意義。
問題是當Task沒有特別的行爲時該怎麼做?我看到一些可能的方法:
- 實例化每項任務的具體策略,而當
Task
不是Plannable
實現「虛擬」的策略(本項選擇如下圖所示)。還有奇怪的可空Start
和Finish
變量遍佈代碼,在這種情況下... - 有
nullable
IPlanningStrategy變量的情況下的任務,不能有計劃,只有當它被「提升」戰略的具體實例是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
(或者說,以完成任務所需要的剩餘小時數),並說parameter2
爲LastDate
(相當於限制日期,即最後允許的日期完成的任務)。這個參數自然屬於特定的Task
,但只有當它實現這個特定的StrategyA
。
看來,實例化外部Task
類策略沒有意義嗎?或者這應該是一些Factory
方法的工作?
感謝您的回答。如果可以具有可空的'Task.planninStrategy',那麼當然,我不需要「dummy」'NoStrategy'類,並且可以被刪除。關於第二點,我的客戶對'開始'和'完成'非常感興趣,因爲如果Task是Plannable,整個Planning的行爲就是向他們展示Start和Finish。但是,'Start'和'Finish'可以用與'Task.CalculatePlan()'類似的方式表示,即。檢查null並返回'開始/完成'如果不爲空? – buggy08
是的,你可以做到這一點,如果你需要返回開始/完成把它們放在一個對象中,更改你的界面,以返回你的客戶期望滿足此合同的任何信息。相應地處理異常。 – DarthVader
這裏有更多的問題:-)我剛剛擴展問題... – buggy08