具体策略的战略模式 [英] Strategy Pattern with Dummy concrete strategy
问题描述
参考发布的问题此处,如果这是解决扩展类的可选行为的好方法,通过使用组合,不继承。 可计划
行为在这里由策略模式扩展。
Refering to posted question here, could you please comment if this is good approach to solve OPTIONAL behaviour for extending class, by using composition, not inheritance. Plannable
behaviour is here extended by Strategy pattern.
所以,课程任务
可以可选地具有各种行为的任何组合。 可计划
只是其中之一,因此继承在这里显然没有意义。
So, class Task
could optionally have any combination of various behaviours. Plannable
is just one of them, therefore inheritance does obviously not making sense here.
问题是如何做任务没有特殊的行为?我看到几种可能的方法:
Question is what to do when Task does not have particular behaviour ? I see few possible approaches:
- 为每个任务实例化具体的策略,并在
任务
不是可计划
(此选项如下所示)。在这种情况下,有奇怪的可空的开始
和完成
变量,<...> - 具有
可空值
案例任务中的IPlanningStrategy变量将不会被计划,并且仅在升级为可计划
。
- Instantiate concrete strategy for each task, and implement "Dummy" strategy when
Task
is notPlannable
(this alternative is shown below). There are weird nullableStart
andFinish
variables all over the code, in this case... - Having
nullable
IPlanningStrategy variable in the case task won't be planned, and instantiate with concrete Strategy only when it is "promoted" to bePlannable
.
替代(1)应该是这样的:
Alternative (1) should be something like this:
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
}
现在我看到不同的**非常重要的**这里的问题。我的具体策略类中的每一个都包含算法,当然这对于实现该算法的所有任务来说都是共享的,附加参数仅属于特定的任务
。
Now I see different ** VERY IMPORTANT** problem here. Each of my concrete Strategy class holds, beside algorithm, which is of course shared for all tasks implementing this algorithm, additional parameters, which belongs only to particular Task
.
您可以想象 parameter1
as Effort
(或者说,完成任务所需的剩余时间),并说 parameter2
as LastDate
(表示约束日期,即最后允许的日期完成任务)。这个参数自然属于特定的 Task
,但只有当它实现了这个特定的 StrategyA
。
You can imagine parameter1
as Effort
(or, say, number of remaining hours required to complete task), and say parameter2
as LastDate
(representing constraint date, ie. last allowable date to finish task). This parameters naturally belongs to particular Task
, but only if it implements this particular StrategyA
.
似乎在 Task
之外的实例化策略没有意义?或者这应该是一些工厂
方法的工作?
It seems that instantiate strategy outside Task
class does not make sense ? Or this should be job for some Factory
method ?
推荐答案
IMO你在任务
类中暴露了太多信息。我会做如下:
IMO you are exposing too much information in your Task
class. I would do as follows:
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();
}
}
您的客户不知道开始,完成我不会看到作为算法的容器的责任。
Your client shouldnt know start, finish, i dont see that as responsibility of a container for algorithms.
此外,如果您的NoPlanStrategy没有做任何事情,为什么要介绍它。 removeit。
Moreover, if your NoPlanStrategy not doing anything, why introduce it. removeit.
这篇关于具体策略的战略模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!