Автор оригинала: Krzysztof Woyke.
1. введение
Шаблон проектирования Builder является одним из наиболее широко используемых шаблонов создания. Это помогает нам строить сложные объекты.
Написание строителей вручную является громоздким и подверженным ошибкам. Поэтому мы должны использовать специальные инструменты для их автоматической генерации, когда это возможно.
В этом уроке мы рассмотрим различные способы автоматического создания классов конструкторов в IntelliJ IDEA. Мы рассмотрим встроенные функции, которые IntelliJ предоставляет из коробки, а также сторонние плагины.
2. Начальная настройка
На протяжении всей этой статьи мы будем использовать версию 2019.1.3 IntelliJ IDEA Community edition, которая является самой последней версией на момент написания статьи. Однако все методы, представленные в примерах, должны отлично работать и с любой другой версией IDEA.
Давайте начнем с определения класса Book , для которого мы создадим конструктор:
public class Book { private String title; private Author author; private LocalDate publishDate; private int pageCount; // standard constructor(s), getters and setters }
3. Использование встроенных функций IntelliJ
Чтобы создать конструктор для Книга класс используя встроенные инструменты IntelliJ, нам нужен соответствующий конструктор.
Давайте создадим его:
public Book(String title, Author author, LocalDate publishDate, int pageCount) { this.title = title; this.author = author; this.publishDate = publishDate; this.pageCount = pageCount; }
Теперь мы готовы создать конструктор. Поэтому давайте наведем курсор на созданный конструктор и откроем всплывающее окно Рефакторинг этого , нажав Ctrl+Alt+Shift+T (на ПК) и выбрав Заменить конструктор на Конструктор рефакторинг:
Мы можем дополнительно настроить некоторые параметры для класса builder, такие как его имя и целевой пакет:
В результате мы создали класс Book Builder :
public class BookBuilder { private String title; private Author author; private LocalDate publishDate; private int pageCount; public BookBuilder setTitle(String title) { this.title = title; return this; } public BookBuilder setAuthor(Author author) { this.author = author; return this; } public BookBuilder setPublishDate(LocalDate publishDate) { this.publishDate = publishDate; return this; } public BookBuilder setPageCount(int pageCount) { this.pageCount = pageCount; return this; } public Book createBook() { return new Book(title, author, publishDate, pageCount); } }
3.1. Префикс пользовательских установщиков
Общепринятой практикой является использование с префиксом для методов setter в классах builder.
Чтобы изменить префикс по умолчанию, нам нужно выбрать значок Переименовать префикс установщиков в правом верхнем углу окна параметров :
3.2. Статический внутренний конструктор
Некоторые из нас могут предпочесть реализовать конструкторы в виде статических внутренних классов, как описано Джошуа Блохом в эффективной Java .
Если это так, нам нужно предпринять несколько дополнительных шагов для достижения этой цели, используя функцию IntelliJ Replace Constructor with Builder .
Прежде всего, нам нужно вручную создать пустой внутренний класс и сделать конструктор закрытым:
public class Book { private String title; private Author author; private LocalDate publishDate; private int pageCount; public static class Builder { } private Book(String title, Author author, LocalDate publishDate, int pageCount) { this.title = title; this.author = author; this.publishDate = publishDate; this.pageCount = pageCount; } // standard getters and setters }
Кроме того, мы должны выбрать Использовать существующий в окне параметров и указать на наш недавно созданный класс:
4. Использование плагина Inner Builder
Давайте теперь посмотрим, как мы можем создать конструктор для Книга использование класса Внутренний Строитель плагин.
После установки плагина мы можем открыть всплывающее окно Generate , нажав Alt+Insert (на ПК) и выбрав Builder… опция:
В качестве альтернативы мы можем вызвать плагин Inner Builder напрямую, нажав Alt+Shift+B (на ПК):
Как мы видим, есть несколько вариантов, из которых мы можем выбрать, чтобы настроить созданный конструктор.
Давайте посмотрим, как строитель генерируется, когда все параметры не отмечены:
public static final class Builder { private String title; private Author author; private LocalDate publishDate; private int pageCount; public Builder() { } public Builder title(String val) { title = val; return this; } public Builder author(Author val) { author = val; return this; } public Builder publishDate(LocalDate val) { publishDate = val; return this; } public Builder pageCount(int val) { pageCount = val; return this; } public Book build() { return new Book(this); } }
Плагин Inner Builder по умолчанию реализует конструкторы как статические внутренние классы.
5. Использование плагина Builder Generator
Наконец, давайте посмотрим, как работает генератор Builder/|.
Аналогично, что касается внутреннего конструктора, мы можем либо нажать Alt+Insert (на ПК) и выбрать Builder option, либо использовать Alt+Shift+B shortcut.
Как мы видим, у нас есть три варианта на выбор для настройки BookBuilder :
Давайте оставим все опции непроверенными и посмотрим сгенерированный класс builder:
public final class BookBuilder { private String title; private Author author; private LocalDate publishDate; private int pageCount; private BookBuilder() { } public static BookBuilder aBook() { return new BookBuilder(); } public BookBuilder withTitle(String title) { this.title = title; return this; } public BookBuilder withAuthor(Author author) { this.author = author; return this; } public BookBuilder withPublishDate(LocalDate publishDate) { this.publishDate = publishDate; return this; } public BookBuilder withPageCount(int pageCount) { this.pageCount = pageCount; return this; } public Book build() { Book book = new Book(); book.setTitle(title); book.setAuthor(author); book.setPublishDate(publishDate); book.setPageCount(pageCount); return book; } }
Первый вариант, который предоставляет плагин Builder Generator для настройки созданного класса builder – Inner builder– , довольно понятен.
Два других, однако, более интересны, и мы рассмотрим их в следующих разделах.
5.1. Вариант метода “но”
Если мы выберем этот параметр, плагин добавит метод but() в класс BookBuilder :
public BookBuilder but() { return aBook().withTitle(title).withAuthor(author) .withPublishDate(publishDate).withPageCount(pageCount); }
Теперь давайте представим, что мы хотим создать три книги с одним и тем же автором и одинаковым количеством страниц, но с разными названиями и датами публикации. Мы можем создать базовый конструктор с уже заданными общими свойствами, а затем использовать метод but() для создания из него нового Book Builder s (и Book s позже).
Давайте рассмотрим пример:
BookBuilder commonBuilder = BookBuilder.aBook().withAuthor(johnDoe).withPageCount(123); Book my_first_book = commonBuilder.but() .withPublishDate(LocalDate.of(2017, 12, 1)) .withTitle("My First Book").build(); Book my_second_book = commonBuilder.but() .withPublishDate(LocalDate.of(2018, 12, 1)) .withTitle("My Second Book").build(); Book my_last_book = commonBuilder.but() .withPublishDate(LocalDate.of(2019, 12, 1)) .withTitle("My Last Book").build();
5.2. Используйте опцию с одним полем
Если мы выберем этот параметр, сгенерированный конструктор будет содержать ссылку на созданный объект Book вместо всех свойств книги:
public final class BookBuilder { private Book book; private BookBuilder() { book = new Book(); } public static BookBuilder aBook() { return new BookBuilder(); } public BookBuilder withTitle(String title) { book.setTitle(title); return this; } public BookBuilder withAuthor(Author author) { book.setAuthor(author); return this; } public BookBuilder withPublishDate(LocalDate publishDate) { book.setPublishDate(publishDate); return this; } public BookBuilder withPageCount(int pageCount) { book.setPageCount(pageCount); return this; } public Book build() { return book; } }
Это немного другой подход к созданию класса конструктора, который может пригодиться в определенных ситуациях.
6. Заключение
В этом уроке мы рассмотрели различные способы создания классов конструкторов в IntelliJ.
Обычно лучше использовать такие инструменты для автоматической генерации наших строителей . Каждый из представленных нами вариантов имеет свои плюсы и минусы. Какой подход мы на самом деле выбираем, это скорее вопрос вкуса и индивидуальных предпочтений.