Перейти к основному содержимому

Реализация шаблона метода шаблона в Java

· 3 мин. чтения

1. Обзор

В этом кратком руководстве мы увидим, как использовать шаблон метода шаблона — один из самых популярных шаблонов GoF .

Это упрощает реализацию сложных алгоритмов за счет инкапсуляции логики в одном методе.

2. Реализация

Чтобы продемонстрировать, как работает шаблон метода шаблона, давайте создадим простой пример, представляющий создание компьютерной станции.

Учитывая определение шаблона, структура алгоритма будет определена в базовом классе, который определяет метод шаблона build () :

public abstract class ComputerBuilder {

// ...

public final Computer buildComputer() {
addMotherboard();
setupMotherboard();
addProcessor();
return new Computer(computerParts);
}

public abstract void addMotherboard();
public abstract void setupMotherboard();
public abstract void addProcessor();

// ...
}

Класс ComputerBuilder отвечает за описание шагов, необходимых для сборки компьютера, путем объявления методов добавления и настройки различных компонентов , таких как материнская плата и процессор.

Здесь метод build() является методом шаблона , который определяет этапы алгоритма сборки частей компьютера и возвращает полностью инициализированные экземпляры компьютера .

Обратите внимание, что он объявлен как final , чтобы предотвратить его переопределение.

3. В действии

Когда базовый класс уже установлен, давайте попробуем использовать его, создав два подкласса. Один из них собирает «стандартный» компьютер, а другой — компьютер «высокого класса»:

public class StandardComputerBuilder extends ComputerBuilder {

@Override
public void addMotherboard() {
computerParts.put("Motherboard", "Standard Motherboard");
}

@Override
public void setupMotherboard() {
motherboardSetupStatus.add(
"Screwing the standard motherboard to the case.");
motherboardSetupStatus.add(
"Pluging in the power supply connectors.");
motherboardSetupStatus.forEach(
step -> System.out.println(step));
}

@Override
public void addProcessor() {
computerParts.put("Processor", "Standard Processor");
}
}

А вот вариант HighEndComputerBuilder :

public class HighEndComputerBuilder extends ComputerBuilder {

@Override
public void addMotherboard() {
computerParts.put("Motherboard", "High-end Motherboard");
}

@Override
public void setupMotherboard() {
motherboardSetupStatus.add(
"Screwing the high-end motherboard to the case.");
motherboardSetupStatus.add(
"Pluging in the power supply connectors.");
motherboardSetupStatus.forEach(
step -> System.out.println(step));
}

@Override
public void addProcessor() {
computerParts.put("Processor", "High-end Processor");
}
}

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

Теперь давайте посмотрим на это в действии:

new StandardComputerBuilder()
.buildComputer();
.getComputerParts()
.forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));

new HighEndComputerBuilder()
.buildComputer();
.getComputerParts()
.forEach((k, v) -> System.out.println("Part : " + k + " Value : " + v));

4. Шаблонные методы в основных библиотеках Java

Этот шаблон широко используется в основных библиотеках Java, например, в java.util.AbstractList или java.util.AbstractSet.

Например, Abstract List обеспечивает скелетную реализацию интерфейса List . ``

Примером шаблонного метода может быть метод addAll() , хотя он явно не определен как final:

public boolean addAll(int index, Collection<? extends E> c) {
rangeCheckForAdd(index);
boolean modified = false;
for (E e : c) {
add(index++, e);
modified = true;
}
return modified;
}

Пользователям нужно только реализовать метод add() :

public void add(int index, E element) {
throw new UnsupportedOperationException();
}

Здесь программист обязан предоставить реализацию для добавления элемента в список по заданному индексу (вариантная часть алгоритма листинга).

5. Вывод

В этой статье мы показали шаблон метода шаблона и то, как его реализовать в Java.

Шаблон метода шаблона способствует повторному использованию кода и разделению, но за счет использования наследования.

Как всегда, все примеры кода, показанные в этой статье, доступны на GitHub .