Цепочка ответственности: петля или следующая?

Я реализую цепочку ответственности.

У меня разные политики, которые можно комбинировать в списке, и у меня есть Процессор, который обрабатывает список политик. Каждая политика может обрабатывать CustomInput и может выбирать, нужно ли обрабатывать остальные политики.

interface Policy {    
  public boolean process(CustomInput input);    
}

interface Processor {    
  public void process(List<Policy> policies, CustomInput input)    
}

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

Мой коллега предложил передать следующую Политику каждой Политике и позволить им называть (или нет) следующий (например, FilterChain).

Мой вопрос следующий:

Есть ли какие-либо преимущества, которые я не вижу во втором решении (передавая следующую политику для текущей обработки), за цикл по каждой политике и проверку ее результата?

Ответ 1

Идея прохода следующего по мне не имеет смысла. Поэтому я хочу цепочку:

A - B - C - D

Как C знает о D? Если это в коде для C, то любое изменение в цепочке будет огромной проблемой для реализации.

Цепочка должна либо следовать другому пути, который уже существует, как, например, респонденты, когда они просто пробуждают запросы на помощь каждому своему соответствующему родителю (пример в книге "Банда четырех" ), или вам нужно построить цепочка, поэтому в нижней части секции в Go4 они упоминают составной паттерн как законопослушный соучастник.

Обратите также внимание на то, что одной из основных причин для выполнения Цепочки Ответственности является то, что типы, которые могут работать с элементом, различны. Что делает его реализацию с идеальным интерфейсом в Java.

Чтобы ответить на ваш основной вопрос: преимущество использования Цепочки Ответственности в этом случае - в два раза: 1. вы не делаете объект бога, который знает обо всех вещах, которые когда-либо могли бы достичь цели (успешное построение политика) и 2. вам не нужно вводить много уродливого проверяющего кода, чтобы увидеть, когда вы достигли конечной точки, потому что тот, кто его обрабатывает, не называя своего преемника, будет запрашивать возврат готового элемента.

Ответ 2

Не могли бы вы реализовать половинное решение, которое позволяет обоим компонентам иметь контроль над деталями?

interface Policy {
  public Policy process(CustomInput input, Policy defaultNext);
}

process может по умолчанию возвращать defaultNext, если у него нет собственного выбора.