需要一个设计模式来删除对象创建中的枚举和switch语句

时间:2010-10-09 17:59:24

标签: design-patterns object-construction

假设我正在创建一个体育游戏,在这个游戏中,玩家可以玩各种姿势,攻击,防御等。 所以我首先创建一个基类:

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

我应该考虑什么解决方案?这是哪种设计模式?

4 个答案:

答案 0 :(得分:4)

如果你必须小规模地做这件事,那么转换并不是很糟糕,特别是如果它住在一个地方。

如果你必须在中等规模上这样做,你可能要考虑改善内部因素 - 史蒂夫·埃林格的建议是合理的。我个人更喜欢使用IDictionary<MyEnum, Action<T>>,其中Action返回相关类的新实例。

如果您必须在宏观或可配置的范围内执行此操作,您可能应该查看一个IoC控制器,例如structuremap或ninject,或者这些天酷孩子正在玩的任何东西。

答案 1 :(得分:3)

听起来像Factory pattern

然而,有一个switch case可能并不坏,它会打开一个enum / string来返回正确类型的对象....只要它在一个地方被隔离

答案 2 :(得分:1)

的确,你想要的是一个抽象的工厂。实施工厂的难易程度取决于您使用的语言。例如,php允许变量类名,因此您只需发送类名并获取新的$ classname。但是,其他语言不允许这样做。事实上,如果您的语言没有这样做,那么您已经创建了一个工厂类!

除非你想用反射来模拟php的功能,否则你无法做到更优雅。

答案 3 :(得分:1)

处理切换的一种方法是让工厂声明一个Types数组,然后使用枚举作为数组的索引,如下所示:

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;
    }
}