Статьи

Шаблоны креационного дизайна: шаблон Builder

Ранее мы смотрели на фабрику и на абстрактную фабричную модель. Эти шаблоны служат своей цели и могут быть действительно полезными, однако есть случаи, когда нам нужно создать очень сложный объект, и для его создания требуются разные шаги, каждый из которых требует разных действий. В таких случаях шаблон строителя может быть действительно полезным.
Шаблон проектирования строителя является шаблоном творческого проектирования и может использоваться для пошагового создания сложных объектов.

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

  • Инкапсулируйте создание и сборку частей сложного объекта в отдельный объект Builder .
  • Делегируйте создание объекта объекту Builder вместо непосредственного создания объектов.

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

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

Итак, начнем с класса, отвечающего за отправку электронной почты.

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
package com.gkatzioura.design.creational.builder;
 
public class Email {
 
    private final String title;
    private final String recipients;
    private final String message;
 
    public Email(String title, String recipients, String message) {
        this.title = title;
        this.recipients = recipients;
        this.message = message;
    }
 
    public String getTitle() {
        return title;
    }
 
    public String getRecipients() {
        return recipients;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void send() {
 
    }
}

Как видите, класс содержит только три строковых поля, и на них нет дополнительной обработки. Поэтому мы создадим класс построителя, который будет обрабатывать форматирование сообщения, представление получателя и создание класса Email.

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.gkatzioura.design.creational.builder;
 
import java.util.HashSet;
import java.util.Set;
 
public class EmailBuilder {
 
    private Set recipients = new HashSet();
    private String title;
    private String greeting;
    private String mainText;
    private String closing;
 
    public EmailBuilder addRecipient(String recipient) {
        this.recipients.add(recipient);
        return this;
    }
 
    public EmailBuilder removeRecipient(String recipient) {
        this.recipients.remove(recipient);
        return this;
    }
 
    public EmailBuilder setTitle(String title) {
        this.title = title;
        return this;
    }
 
    public EmailBuilder setGreeting(String greeting) {
        this.greeting = greeting;
        return this;
    }
 
    public EmailBuilder setMainText(String mainText) {
        this.mainText = mainText;
        return this;
    }
 
    public EmailBuilder setClosing(String closing) {
        this.closing = closing;
        return this;
    }
 
    public Email create() {
 
        String message = greeting+"\n"+mainText+"\n"+closing;
        String recipientSection = commaSeparatedRecipients();
 
        return new Email(title,recipientSection,message);
    }
 
    private String commaSeparatedRecipients() {
 
        StringBuilder sb = new StringBuilder();
        for(String recipient:recipients) {
            sb.append(",").append(recipient);
        }
 
        return sb.toString().replaceFirst(",","");
    }
 
}

Следующий шаг — сделать создание электронной почты более строгим, чтобы создание электронной почты было возможно только через EmailBuilder.

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package com.gkatzioura.design.creational.builder;
 
import java.util.HashSet;
import java.util.Set;
 
public class Email {
 
    private final String title;
    private final String recipients;
    private final String message;
 
    private Email(String title, String recipients, String message) {
        this.title = title;
        this.recipients = recipients;
        this.message = message;
    }
 
    public String getTitle() {
        return title;
    }
 
    public String getRecipients() {
        return recipients;
    }
 
    public String getMessage() {
        return message;
    }
 
    public void send() {
 
    }
 
    public static class EmailBuilder {
 
        private Set recipients = new HashSet();
        private String title;
        private String greeting;
        private String mainText;
        private String closing;
 
        public EmailBuilder addRecipient(String recipient) {
            this.recipients.add(recipient);
            return this;
        }
 
        public EmailBuilder removeRecipient(String recipient) {
            this.recipients.remove(recipient);
            return this;
        }
 
        public EmailBuilder setTitle(String title) {
            this.title = title;
            return this;
        }
 
        public EmailBuilder setGreeting(String greeting) {
            this.greeting = greeting;
            return this;
        }
 
        public EmailBuilder setMainText(String mainText) {
            this.mainText = mainText;
            return this;
        }
 
        public EmailBuilder setClosing(String closing) {
            this.closing = closing;
            return this;
        }
 
        public Email build() {
 
            String message = greeting+"\n"+mainText+"\n"+closing;
            String recipientSection = commaSeparatedRecipients();
 
            return new Email(title,recipientSection,message);
        }
 
        private String commaSeparatedRecipients() {
 
            StringBuilder sb = new StringBuilder();
            for(String recipient:recipients) {
                sb.append(",").append(recipient);
            }
 
            return sb.toString().replaceFirst(",","");
        }
 
    }
}

Конечный результат использования шаблона построителя для создания электронного письма будет таким.

1
2
3
4
5
6
7
Email email = new Email.EmailBuilder()
    .addRecipient("[email protected]")
    .setMainText("Check the builder pattern")
    .setGreeting("Hi John!")
    .setClosing("Regards")
    .setTitle("Builder pattern resources")
    .build();

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

Вы можете найти исходный код на github .

В следующем блоге мы поговорим о синглтоне .

Также я собрал шпаргалку, содержащую сводку шаблонов креационного дизайна.
Зарегистрируйтесь в ссылке, чтобы получить его.

Опубликовано на Java Code Geeks с разрешения Эммануила Гкациоураса, партнера нашей программы JCG. Смотрите оригинальную статью здесь: Шаблоны креационного дизайна: Шаблон Builder

Мнения, высказанные участниками Java Code Geeks, являются их собственными.