Подтвердить что ты не робот

Как избежать коммутационного случая в методе factory дочерних классов

Допустим, у нас есть семейство классов (карт, для этого), и нам нужно создать их на основе некоторого идентификатора. Метод factory будет выглядеть следующим образом:

public Card GetCard(int cardNumber) 
{
   switch(cardNumber) 
   {
     case 13: return new King();
     case 12: return new Queen();
     case 11: return new Jack();          
   }

   //...
}

Я хочу избежать этого switch. Зачем? Возможно, я хочу повторно использовать это сравнение в этой функции.

Что я придумал, это примерно так:

private Dictionary<int, Type> cardTypes = 
 { 
   {13, typeof(King)},
   {12, typeof(Queen)},
   {11, typeof(Jack)}
 };

 public Card GetCard(int cardNumber) 
 {        
    var cardType = cardTypes[cardNumber];
    var instance = Activator.CreateInstance(cardType);
    return (Card)instance;
 }

Однако это решение использует отражение, которое дорого, и также проблематично, когда у вас есть более одного "идентификатора" (например, 1 и 14 оба дают Ace - следует ли добавить 2 слова в словарь?).

Какая наилучшая практика в этом сценарии?

4b9b3361

Ответ 1

Вместо сохранения типа в словаре вы можете сохранить Func<Card>:

private Dictionary<int, Func<Card>> cardFactories = 
{
    { 13, () => new King() },
    // etc
}

public Card GetCard(int cardNumber) 
{        
    var factory = cardFactories[cardNumber];
    return factory();
}

В случае карт, я бы, вероятно, сделать их неизменны, чтобы начать с и просто заполнить словарь с самих карт, но это другое дело:)