参考已发布的问题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
}
现在我在这里看到不同的**非常重要的**问题。除了算法之外,我的每个具体策略类都包含在实现此算法的所有任务中共享的附加参数,这些参数仅属于特定Task
。
您可以将parameter1
想象为Effort
(或者说,完成任务所需的剩余小时数),并将parameter2
称为LastDate
(表示约束日期,即。完成任务的最后允许日期)。此参数自然属于特定Task
,但前提是它实现了此特定StrategyA
。
似乎Task
类以外的实例化策略没有意义?或者这应该是一些Factory
方法的工作?
答案 0 :(得分:0)
IMO您在Task
课程中暴露了太多信息。我会这样做:
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没有做任何事情,为什么要介绍它。 removeit。