对于个人项目,我正在开发一款基于网络的小游戏。
我有一个Card
类,它具有Status
属性,并且在整个地方都有case语句。我想,嘿,Replace Conditional with Polymorphism这是一个很好的机会!
问题是,我有几种方法可以做这样的事情:
public class Card
{
public void ChangeStatus()
{
switch (Status)
{
case MyStatusEnum.Normal:
Status = MyStatusEnum.Underwater;
break;
case MyStatusEnum.Underwater:
Status = MyStatusEnum.Dead;
break;
// etc...
}
}
}
在新NormalCard
课程中重构时,我会覆盖ChangeStatus
这样的方法:
public override void ChangeStatus()
{
base.Status = MyStatusEnum.Underwater;
}
问题是NormalCard
的此对象的状态为Underwater
。我无法重新分配this
的类型,我真的不想将方法的返回值从void
更改为CardBase
。我有什么选择?有没有一种标准的方法呢?
编辑 Tormod让我直截了当。我想要State Pattern。谢谢大家!
答案 0 :(得分:3)
在您的情况下,我有一个包含Card
属性的CardStatus
对象。 CardStatus
的子类型对应于先前的枚举值。重构行为取决于当前状态,但状态转换除了在CardStatus子类型内。
第一个示例中的状态转换IMO应保留在Card
对象中。状态变化感觉更像是包含卡的行为而不是状态对象。您可以做的是让CardStatus对象告诉您在事件发生后要转换到的状态。
一个粗略的例子:(显然可以使用更多的变体。)
interface ICardStatus {
ICardStatus NextStatus(Card card);
void DoStuff(Card card);
}
class Card {
ICardStatus Status = new NormalCardStatus();
void DoStuff() {
Status.DoStuff(this);
}
void ChangeStatus() {
Status = Status.NextStatus(this);
}
}
class NormalCardStatus : ICardStatus {
ICardStatus NextStatus(Card card) {
return new UnderwaterCardStatus();
}
void DoStuff(Card card) {
// ...
}
}
class UnderwaterCardStatus : ICardStatus {
ICardStatus NextStatus(Card card) {
return new DeathStatus();
}
void DoStuff(Card card) {
// ...
}
}
class DeathCardStatus : ICardStatus {
ICardStatus NextStatus(Card card) {
// ...
}
void DoStuff(Card card) {
throw new Exception("Cannot do anything while dead");
}
}
答案 1 :(得分:2)
您可以使用多态性编写Status
类:
class Status
{
Status GetNextStatusWhenFooHappens() {}
Status GetNextStatusWhenBarHappens() {}
Status GetNextStatusWhenBloopHappens() {}
}
每个方法都会立即返回要移动到的状态,或者您在case
中执行的任何其他操作。然后,您可以为每个特定状态覆盖这些方法。 Card
类不会对此实现具有多态性,但它将保留多态Status
成员。
答案 2 :(得分:1)
在某些情况下,用多态替换条件很有用,但不清楚它在这里是否合适......至少不是直接枚举。您可以引入“智能枚举”类型而不是MyStatusEnum
,其中每个值都知道“下一个”值 - 那么您不一定会使用多态,但将使用一组固定的值,其信息比标准枚举更多。
另一种方法是让一个简单的Dictionary<MyStatusEnum, MyStatusEnum>
从“当前状态”变为“下一个状态”。这真的取决于你是否还需要做更多的事情。我怀疑我们真的不能仅根据您提供的代码提供非常好的建议。