Статьи

Шаблонный метод Pattern — Использование лямбда-выражений, методы по умолчанию

Шаблонный метод — это один из 23 шаблонов дизайна, описанных в знаменитой книге Эриха Гамма, Ричарда Хелма, Ральфа Джонсона и Джона Влиссидеса « Шаблоны дизайна» . Цель этого шаблона указывается как:

Определите каркас алгоритма в операции, отложив некоторые шаги до подклассов. TemplateMethod позволяет подклассам переопределять определенные этапы алгоритма без изменения структуры алгоритма.

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

реализация различных систем документооборота.

Шаблонный метод может быть применен к описанному выше сценарию путем инкапсуляции системы рабочего процесса в абстрактный класс с несколькими из 4 реализованных задач. И оставьте реализацию оставшихся задач подклассам абстрактного класса.

Итак, вышесказанное при реализации:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
 * Abstract Workflow system
 */
abstract class WorkflowManager2{
  public void doTask1(){
    System.out.println("Doing Task1...");
  }
 
  public abstract void doTask2();
 
  public abstract void doTask3();
 
  public void doTask4(){
    System.out.println("Doing Task4...");
  }
}
 
/**
 * One of the extensions of the abstract workflow system
 */
class WorkflowManager2Impl1 extends WorkflowManager2{
  @Override
  public void doTask2(){
    System.out.println("Doing Task2.1...");
  }
 
  @Override
  public void doTask3(){
    System.out.println("Doing Task3.1...");
  }
}
 
/**
 * Other extension of the abstract workflow system
 */
class WorkflowManager2Impl2 extends WorkflowManager2{
  @Override
  public void doTask2(){
    System.out.println("Doing Task2.2...");
  }
 
  @Override
  public void doTask3(){
    System.out.println("Doing Task3.2...");
  }
}

Позвольте мне пойти дальше и показать, как используются эти реализации рабочих процессов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class TemplateMethodPattern {
  public static void main(String[] args) {
   initiateWorkFlow(new WorkflowManager2Impl1());
   initiateWorkFlow(new WorkflowManager2Impl2());
  }
 
  static void initiateWorkFlow(WorkflowManager2 workflowMgr){
    System.out.println("Starting the workflow ... the old way");
    workflowMgr.doTask1();
    workflowMgr.doTask2();
    workflowMgr.doTask3();
    workflowMgr.doTask4();
  }
}

и на выходе будет ..

01
02
03
04
05
06
07
08
09
10
Starting the workflow ... the old way
Doing Task1...
Doing Task2.1...
Doing Task3.1...
Doing Task4...
Starting the workflow ... the old way
Doing Task1...
Doing Task2.2...
Doing Task3.2...
Doing Task4...

Все идет нормально. Но основная цель этого поста не в том, чтобы создать еще один пост в блоге по шаблонному методу, а в том, чтобы увидеть, как мы можем использовать лямбда-выражения Java 8 и методы по умолчанию . Ранее я уже писал, что в качестве лямбда-выражений могут быть написаны только те интерфейсы, которые имеют один абстрактный метод. В этом примере это означает, что WorkflowManager2 может иметь только одну абстрактную / настраиваемую задачу из 4 задач.

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

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

Вместо абстрактного класса мы будем использовать интерфейс с методами по умолчанию, поэтому наша система рабочего процесса будет выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
interface WorkflowManager{
  public default void doTask1(){
    System.out.println("Doing Task1...");
  }
 
  public void doTask2();
 
  public default void doTask3(){
    System.out.println("Doing Task3...");
  }
 
  public default void doTask4(){
    System.out.println("Doing Task4...");
  }
}

Теперь, когда у нас есть система рабочих процессов с настраиваемой задачей 2, мы продолжим и инициируем некоторые настроенные рабочие процессы, используя лямбда-выражения

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public class TemplateMethodPatternLambda {
  public static void main(String[] args) {
    /**
     * Using lambda expression to create different
     * implementation of the abstract workflow
     */
    initiateWorkFlow(()->System.out.println("Doing Task2.1..."));
    initiateWorkFlow(()->System.out.println("Doing Task2.2..."));
    initiateWorkFlow(()->System.out.println("Doing Task2.3..."));
  }
 
  static void initiateWorkFlow(WorkflowManager workflowMgr){
    System.out.println("Starting the workflow ...");
    workflowMgr.doTask1();
    workflowMgr.doTask2();
    workflowMgr.doTask3();
    workflowMgr.doTask4();
  }
}

Это в небольшом смысле лямбда-выражения могут быть использованы в шаблоне шаблона шаблона