1. Концепция и предыстория
Схема цепочки ответственности: Шаблон цепочки ответственности — это общая схема создания последовательности объектов обработки (например, последовательности операций). Объекту-обработчику может потребоваться выполнить некоторую работу, передать результат другому объекту, который затем выполняет некоторую работу, прежде чем передать его следующему объекту-обработчику, и так далее.
Короче говоря, объект, который необходимо обработать, должен быть обработан в несколько шагов, чтобы сформировать цепочку.После обработки одного шага обработка переходит к следующему шагу.
Код, задействованный в этой статье, находится на github, нажмитеСсылка на сайтВы можете просмотреть исходный код.
В этой статье паттерн цепочки ответственности будет реализован двумя способами: второй — в виде лямбда-выражения и в виде поведения параметра.
Сценарии, используемые в этой статье, следующие:: Чтобы обработать письмо, сначала обработайте заголовок письма, затем проверьте написание письма на наличие ошибок, исправьте неправильные слова, если они есть, и, наконец, обработайте конец письма. Обработка письма таким образом образует цепочку: сначала обработка..., затем обработка... и, наконец, обработка....
2. Модель цепочки ответственности
Основываясь на сценариях, упомянутых выше, диаграмма классов UML выглядит следующим образом.Причина, по которой шаблон цепочки ответственности может формировать цепочку, заключается в том, что существует абстрактный класс обработки.У абстрактного класса обработки будет поле (абстрактный обработчик), которое используется для записи последующих объектов, то есть объекта, который записывает выполнение определенного шага обработки. Тогда абстрактный класс обработки также имеет абстрактный метод, то есть абстрактный метод handleWork.Каждый шаг обработки (узел цепи) будет реализовывать абстрактный метод как логику обработки этого шага.Конечно, его нужно перекинуть на следующий узел цепочки для обработки после обработки. .
- Абстрактный класс Handler, то есть абстрактный класс обработки, содержит поле, которое является преемником абстрактного обработчика, а также метод setSuccessor, который используется для установки следующего обработчика, то есть после этого шага/цепочки. узел обрабатывается, он передается следующему обработчику для продолжения обработки. Абстрактный метод handleWork обеспечивает разные этапы обработки и различную логику обработки.Метод handle здесь тоже играет много ролей, образуя цепочку.После handleWork этого узла цепочки он определяет, есть ли у него следующий обработчик.Некоторые Если да, то следующий обработчик продолжает работу handle->handleWork до конца процесса, а обработчика нет.
public abstract class Handler {
protected Handler successor;
public void setSuccessor(Handler successor) {
this.successor = successor;
}
abstract protected String handleWork(String input);
public String handle(String input) {
//本节点处理完之后返回下一节点
String nextNode = handleWork(input);
if (successor != null) {
return successor.handle(nextNode);
}
return nextNode;
}
}
- Класс AddHeaderHandler, обработчик заголовка письма
public class AddHeaderHandler extends Handler{
@Override
protected String handleWork(String input) {
return "From Raoul, Mario and Alan: " + input;
}
}
- Класс CheckSpellHandler, проверяет правописание букв
public class CheckSpellHandler extends Handler{
@Override
protected String handleWork(String input) {
return input.replaceAll("labda", "lambda");
}
}
- Класс AddFooterHandler, конец обработчика письма
public class AddFooterHandler extends Handler{
@Override
protected String handleWork(String input) {
return input + " Kind regards";
}
}
public class ChainMain {
public static void main(String[] args) {
AddHeaderHandler addHeaderHandler = new AddHeaderHandler();
CheckSpellHandler checkSpellHandler = new CheckSpellHandler();
AddFooterHandler addFooterHandler = new AddFooterHandler();
addHeaderHandler.setSuccessor(checkSpellHandler);
checkSpellHandler.setSuccessor(addFooterHandler);
String test = addHeaderHandler.handle("labda");
System.out.println(test);
}
}
Наконец, консоль выводит это обработанное письмо:
From Raoul, Mario and Alan: lambda Kind regards
3. Модель цепочки ответственности, параметризация поведения, лямбда-рефакторинг
Здесь используется функциональный интерфейс Function
- Function<T,R>
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
}
- LambdaHandler
public class LambdaHandler {
public static Function<String, String> addHeaderHandler() {
return (input) -> "From Raoul, Mario and Alan: " + input;
}
public static Function<String, String> checkSpellHandler() {
return (input) -> input.replaceAll("labda", "lambda");
}
public static Function<String, String> addFooterHandler() {
return (input) -> input + " Kind regards";
}
}
- ChainMain
public class ChainMain {
public static void main(String[] args) {
Function<String, String> addHeaderHandler = LambdaHandler.addHeaderHandler();
Function<String, String> checkSpellHandler = LambdaHandler.checkSpellHandler();
Function<String, String> addFooterHandler = LambdaHandler.addFooterHandler();
String test = addHeaderHandler.andThen(checkSpellHandler).andThen(addFooterHandler).apply("labda");
System.out.println(test);
}
}
- Наконец, консоль выводит это обработанное письмо:
From Raoul, Mario and Alan: lambda Kind regards
Основная функция — это метод andThen по умолчанию интерфейса Function
@FunctionalInterface
public interface Function<T, R> {
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
}
Конечно, для последнего шага обработки узла нам нужно выполнить приложение в возвращаемой в конце Function
String test = addHeaderHandler.andThen(checkSpellHandler).andThen(addFooterHandler).apply("labda");
Если в этой статье есть какие-либо недостатки, пожалуйста, поправьте меня или сделайте хорошие предложения ◕‿◕.Спасибо.
использованная литература: "Java8 бой"