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