将条件替换为多态 - 类型更改时如何处理
本文关键字:何处理 处理 替换 条件 多态 类型 | 更新日期: 2023-09-27 18:26:06
对于一个个人项目,我正在开发一个基于Web的小型游戏。
我有一个具有Status
属性的Card
类,到处都是 case 语句。我想,嘿,这是用多态替换条件的好机会!
问题是,我有几种方法可以做这样的事情:
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 让我直截了当。 我想要状态模式。谢谢大家!
在您的情况下,我有一个包含CardStatus
属性的Card
对象。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");
}
}
你可以用多态性编写Status
类:
class Status
{
Status GetNextStatusWhenFooHappens() {}
Status GetNextStatusWhenBarHappens() {}
Status GetNextStatusWhenBloopHappens() {}
}
每种方法都返回要移动到的状态,或您现在在case
中正在执行的任何其他操作。然后,您可以为每个特定状态覆盖这些方法。Card
类不会与此实现多态,但它将包含多态Status
成员。
用多态性替换条件很有用,但不清楚它在这里是否合适......至少不是直枚举。您可以引入"智能枚举"类型而不是MyStatusEnum
,其中每个值都知道"下一个"值 - 那么你不一定使用多态性,但您将使用一组固定的值,其中包含比标准枚举更多的信息。
另一种选择是从"当前状态"到"下一个状态"的简单Dictionary<MyStatusEnum, MyStatusEnum>
。这真的取决于你是否需要做更多的事情。我怀疑我们真的无法仅根据您提供的代码提供非常好的建议。