Недавно я обсуждал с другим программистом лучший способ рефакторинга огромного (1000 строк) метода, полного инструкций "if".
Код написан на Java, но я думаю, эта проблема может произойти и на других языках, таких как С#.
Чтобы решить эту проблему, он предложил использовать шаблон цепочки ответственности.
Он предложил иметь базовый класс "Handler". Затем "Обработчик1", "Обработчик2" и т.д. Расширят "Обработчик".
Затем у обработчиков будет метод getSuccessor, который либо вернет null (если он был последним из цепочки), либо следующий обработчик цепочки.
Затем функция "handleRequest (Request)" будет либо обрабатывать запрос, либо передать его следующей цепочке, и, если ни одно из предыдущих решений не будет работать, оно вернет только null или выдаст исключение.
Чтобы добавить нового обработчика в цепочку, кодер перейдет к последнему элементу цепочки и скажет, что появился новый элемент. Чтобы что-то сделать, он просто вызовет handleRequest для первого элемента цепочки.
Чтобы решить эту проблему, я предложил использовать другой подход.
У меня также был бы базовый класс "Handler", с "Handler1", "Handler2", как и предыдущий метод.
Однако не было бы метода getSuccessor. Вместо этого у меня будет класс Collection со списком обработчиков (Vector, ArrayList или что-то в этом случае лучше).
Функция handleRequest все равно будет существовать, но она не будет распространять вызов для следующих обработчиков. Он просто обработает запрос или вернет null.
Чтобы обрабатывать запрос, можно использовать
for(Handler handle : handlers){
result = handle.handleRequest(request);
if(result!=null) return result;
}
throw new CouldNotParseRequestException(); //just like in the other approach
Или, чтобы предотвратить дублирование кода, в класс коллекции можно добавить метод parseRequest (запрос). Чтобы добавить новый обработчик, можно перейти к конструктору коллекции (или static {} block или что-то эквивалентному) и просто добавить код "addHandler (new Handler3())".
Какое преимущество цепочки ответственности я пропущу при таком подходе? Какой метод лучше всего (при условии, что существует лучший метод)? Зачем? Какие потенциальные ошибки и проблемы могут возникнуть при каждом методе проектирования?
Для тех, кому нужен контекст, вот что выглядел исходный код:
if(x instanceof Type1)
{
//doSomething1
} else if(x instanceof Type2)
{
//doSomething2
}
//etc.