需要一个设计模式来删除枚举和在对象创建中的切换语句
-
29-09-2019 - |
题
假设我正在创建体育游戏,在这个游戏中,玩家可以玩,攻击,防守等各种位置。因此,我首先创建一个基类:
public abstract class Position
{
public abstract string Name
{
get;
}
}
和子类...
public class Defender : Position
{
public override string Name
{
get { return "Defender"; }
}
}
等等。这一切都很好。
但是现在我需要一个函数来创建这些对象。我需要按位置功能创建。因此,一种可能的解决方案是创建所有位置的枚举,并将此值传递给在枚举上切换并返回适当对象的函数。但这触发了我的代码气味警报。这个灵魂将函数内部的类,枚举和开关联系在一起:
public static Position GetByType(Types position)
{
switch(position)
{
case Types.Defender:
return new Defender();
... and further terrible code
我应该看什么解决方案?这是哪种设计模式?
解决方案
如果您必须小规模执行此操作,则开关并不是很糟糕,尤其是如果它生活在一个地方。
如果您必须在中等规模上这样做,则可能需要考虑将内部设备改进一些 - 史蒂夫·埃林格(Steve Ellinger)的建议是合理的。我个人更喜欢使用 IDictionary<MyEnum, Action<T>>
操作返回所讨论的课程的新实例的地方。
如果您必须以宏伟或可配置的比例进行此操作,则可能应该检查IOC控制器,例如结构图或NInject,或这些天很酷的孩子们玩的任何东西。
其他提示
听起来像是 工厂模式.
但是,拥有一个开关案例可能不是一件坏事 在一个地方孤立.
确实,您想要的是抽象工厂。实施工厂的易度性取决于您使用的语言。例如,PHP允许使用可变类名称,因此您可以在类名中发送并获得新的$ className。但是,其他语言不允许这样做。实际上,如果您的语言不这样做,那么您已经创建了工厂课程!
除非您想使用反射来模拟PHP的作用,否则您实际上没有什么更优雅的事情。
处理交换机的一种方法是让工厂声明类型数组,然后将枚举用作索引中的索引中的数组:
public abstract class Position {
public abstract string Name {
get;
}
}
public class Defender : Position {
public override string Name {
get { return "Defender"; }
}
}
public class Attacker : Position {
public override string Name {
get { return "Attacker"; }
}
}
public static class PositionFactory {
public enum Types {
Defender, Attacker
}
private static Type[] sTypes = new Type[] { typeof(Defender), typeof(Attacker)};
public static Position GetByType(Types positionType) {
return Activator.CreateInstance(sTypes[(Int32)positionType]) as Position;
}
}
不隶属于 StackOverflow