Нужен шаблон проектирования для удаления перечислений и переключения оператора при создании объекта - PullRequest
1 голос
/ 09 октября 2010

Допустим, я создаю спортивную игру, и в этой игре есть различные позиции, на которые игрок может играть, атаковать, защищать и т. Д. Поэтому я начну с создания базового класса:

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 ]

4 голосов
/ 10 октября 2010

Если вам нужно сделать это в небольшом масштабе, переключатель не так уж и плох, особенно если он живет в одном месте.

Если вам нужно сделать это в среднем масштабе, вы, возможно, захотите немного улучшить внутреннее устройство - предложение Стива Эллингера является разумным. Лично я предпочитаю использовать IDictionary<MyEnum, Action<T>>, когда действие возвращает новый экземпляр рассматриваемого класса.

Если вам нужно сделать это в большом или настраиваемом масштабе, вам, вероятно, следует проверить контроллер IoC, например, structmap или ninject, или все, что крутые дети играют сегодня.

3 голосов
/ 09 октября 2010

Похоже на Заводской шаблон .

Однако может быть неплохо иметь регистр переключателя, который включает перечисление / строку для возврата правильного типа объекта .... до тех пор, пока он изолирован в одном месте.

1 голос
/ 10 октября 2010

Один из способов справиться с переключателем - заставить фабрику объявить массив типов, а затем использовать перечисление в качестве индекса массива следующим образом:

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;
    }
}
1 голос
/ 09 октября 2010

Действительно, то, что вы хотите, это абстрактная фабрика.Простота реализации фабрики зависит от языка, который вы используете.Например, php допускает имена переменных классов, поэтому вы можете просто отправить имя класса и получить новое $ classname обратно.Другие языки не позволяют этого, однако.На самом деле, если ваш язык этого не делает, вы уже создали фабричный класс!

На самом деле нет ничего более изящного, что вы можете сделать, если не хотите использовать отражение для симуляции того, что делает php.

...