在此之前,我们了解了工厂和抽象工厂模式。这些模式很有用。然而,有几个案例需要创建一个非常复杂的对象,它需要不同的步骤和操作。在这种情况下,Builder Pattern设计模式非常有用。
构建器Builder Pattern设计模式是一种创建型的设计模式,可用于逐步创建复杂的对象。
假设我们有一个具有许多依赖项的对象,并且需要获取其中的每一个依赖项,就必须发出某些操作。在这种情况下,我们可以使用Builder模式来:
在一个单独的构建器对象中封装、创建和组装复杂对象的各个部分。
将对象创建委托给构建器对象,而不是直接创建对象。
想象一下后端系统必须编写和发送电子邮件的场景。
创建电子邮件可能是一个复杂的过程。您必须指定标题、设置收件人、添加问候语和添加结束语句。您也可能想使用mustache(http://mustache.github.io/)。不用说,有很多种选择。
为创建电子邮件所需的所有操作设置一个类可能会使我们的类变得臃肿并失去其最初的目的。
因此,我们将从负责发送电子邮件的类开始。
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() {
}
}
如您所见,这个类只包含三个字符串字段,并且没有额外的处理。因此,我们将创建一个builder类,该类将处理消息格式、接收方表示和电子邮件类的创建。
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(",","");
}
}
下一步是使电子邮件创建更加严格,以便只能通过电子邮件生成器创建电子邮件。
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(",","");
}
}
}
使用Builder模式创建电子邮件的最终结果如下:
Email email = new Email.EmailBuilder()
.addRecipient("john@Doe.com")
.setMainText("Check the builder pattern")
.setGreeting("Hi John!")
.setClosing("Regards")
.setTitle("Builder pattern resources")
.build();
总之,通过使用Builder设计模式,我们能够创建一个复杂的对象及其复杂的部分。
您可以在GitHub(https://github.com/gkatzioura/DesignPatterns)上找到源代码。