Зачем нам нужен строитель?
Использование конструктора или статического фабричного метода имеет ограничение – они плохо масштабируются. Если в классе много полей, список аргументов конструктора или статического фабричного метода довольно длинный, и мы можем получить неправильный порядок при вызове метода. Это еще хуже, если многие поля являются необязательными. Класс builder пригодится.
Что такое строитель
Класс builder обычно является статическим классом-членом класса, который он создает. Вместо того, чтобы создавать нужный объект напрямую, клиент вызывает конструктор с требуемыми полями и получает объект builder. Затем клиент вызывает методы, подобные установщику, для установки полей. Наконец, клиент вызывает метод build
без параметров для создания интересующего объекта.
Рассмотрим этот сценарий, мы хотим приготовить рецепт, и многие ингредиенты являются необязательными.
public class ChickenCongeeRecipe { private final int riceWeight; private final int waterWeight; private final int chickenWeight; private final int saltWeight; private final int gingerWeight; private final int springOnionWeight; public static class Builder { // required fields private final int riceWeight; private final int waterWeight; private final int chickenWeight; // optional fields - default to 0 private int saltWeight = 0; private int gingerWeight = 0; private int springOnionWeight = 0; public Builder(int riceWeight, int waterWeight, int chickenWeight) { this.riceWeight = riceWeight; this.waterWeight = waterWeight; this.chickenWeight = chickenWeight; } public Builder saltWeight(int val) { saltWeight = val; return this; } public Builder gingerWeight(int val) { gingerWeight = val; return this; } public Builder springOnionWeight(int val) { springOnionWeight = val; return this; } public ChickenCongeeRecipe build() { return new ChickenCongeeRecipe(this); } } private ChickenCongeeRecipe(Builder builder) { riceWeight = builder.riceWeight; waterWeight = builder.waterWeight; chickenWeight = builder.chickenWeight; saltWeight = builder.saltWeight; gingerWeight = builder.gingerWeight; springOnionWeight = builder.springOnionWeight; } }
И клиент может создать объект, используя
ChickenCongeeRecipe chickenCongee = new ChickenCongeeRecipe.Builder(100, 800, 50).saltWeight(6).gingerWeight(20).springOnionWeight(20).build();
Созданный объект обычно является неизменяемым.
Вывод
У строителя тоже есть своя оборотная сторона. Это дороже по сравнению с конструкторами или статическими заводскими методами. Это может быть проблемой в приложениях, критически важных для производительности. Чтобы сделать это стоящим, список параметров, вероятно, должен быть больше четырех. Сказав это, если мы начнем с конструкторов и в будущем потребуется добавить дополнительные поля, конструктор останется на месте.
Оригинал: “https://dev.to/sheng_wu/effective-java-why-do-we-need-a-builder-2em”