2016-05-05 7 views
0

Прямо сейчас у меня есть следующая функция, которая не выглядит очень хорошо ко мне:Создание класса на основе идентификатора

string input = "??"; 
Letter output = null; 

switch(input[0]) 
{ 
    case LetterA.Id: // = 'A' 
     output = new LetterA(); 
     break; 

    case LetterB.Id: // = 'B' 
     output = new LetterB(); 
     break; 

    case LetterC.Id: // = 'C' 
     output = new LetterC(); 
     break; 

    // ... 
} 

if (output == null) 
    throw new Exception(); 

output.Parse(input); 

return output; 

Есть ли лучше/короткий путь, чтобы решить эту проблему и создать классы, основанные на Идентификатор?

+3

о Factory pattern –

ответ

0

У вас будет работа, и это не редкость.

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

//example of second 

Dictionary<string, Letter> PrototypeLetters = new Dictionary<string, Letter>(); 

//... 
output = PrototypeLetters[input]->MakeClone(); 
//where make clone is virtual in Letter returning a Letter (of derived type as Letter) 
//still need to handle case where input is not found 

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

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

Считаете ли вы, что этот вариант лучше, зависит от того, какие критерии вы сравниваете.

+0

Вместо того, чтобы клонировать объект, я бы пошел с делегатом, который создает объект такого типа. – Servy

+0

Да, делегат был первым из моих двух предложений. Я думаю, что это было бы более эффективно для случаев, когда все производные типизированные были построены с одинаковыми параметрами, но опция clone не требует этого. – ROX

+0

Я уже думал об использовании Диктонар, но я не думал о делегатах. Мне нравится эта идея - поэтому мне не нужно сначала создавать экземпляр объекта. – random314

0

Вы можете использовать отражение. Предполагается, что Letter, LetterA, LetterB и т. Д. Все живут в одной и той же сборке.

var letterType = typeof(Letter).Assembly.GetTypes() 
    .Where(t => t.Name == "Letter" + input[0]); 
var output = Activator.CreateInstance(letterType) as Letter; 

Пожалуйста, обратите внимание, что выше должна быть какая-то ошибка проверка добавил к нему в случае, если тип не может быть найден или не может быть приведен к Letter после конкретизации.

+0

Использование отсрочки для отражения, если существует «лучший» способ или обходной путь. – niksofteng

+0

@nikhilvartak: «лучше» очень субъективно. Если это какая-то архитектура подключаемого модуля, то постоянно менять оператор 'switch' внутри фабрики - это королевская PITA. «Отражение медленное», что, я уверен, будет вашим ответом, это миф, который разработчики играли на протяжении многих лет. Да, если вы пишете систему в реальном времени или игру, то это, вероятно, не подходит, но для подавляющего большинства коммерческих/коммерческих приложений доступ к базе данных намного медленнее, чем немного отражения. –

Смежные вопросы