Builder Pattern 이란?
- 싱글톤, 팩토리 패턴과 마찬가지로 GoF의 생성 패턴에 속하는 패턴입니다.
- 원래 사용하던 자바빈즈 패턴의 경우, 생성자에 맞게 파라미터를 일일이 설정해줘야 하며, 만약 그러한 생성자가 없을경우 일일이 setter를 활용해 데이터를 입력해줘야 합니다.
- 하지만 후자의 경우 객체가 완전히 생성되기 전까지 데이터의 일관성이 깨지기 때문에 Thread safe를 위해 추가 작업이 필요합니다.
- 빌더 패턴으로 객체를 생성하게 되면 필요한 데이터만 넣어서 객체를 생성할 수 있기 때문에 이러한 불편함을 개선할 수 있습니다.
클라이언트 프로그램으로부터 팩토리 클래스로 많은 파라미터를 넘겨줄 때 타입, 순서 등에 대한 관리가 어려워져 에러가 발생할 확률이 높아집니다.
경우에 따라 필요 없는 파라미터들에 대해서 팩토리 클래스에 일일이 null 값을 넘겨줘야 합니다.
생성해야 하는 sub class가 무거워지고 복잡해짐에 따라 팩토리 클래스 또한 복잡해집니다.
public class Computer {
//required parameters
private String HDD;
private String RAM;
//optional parameters
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public String getHDD() {
return HDD;
}
public String getRAM() {
return RAM;
}
public boolean isGraphicsCardEnabled() {
return isGraphicsCardEnabled;
}
public boolean isBluetoothEnabled() {
return isBluetoothEnabled;
}
private Computer(ComputerBuilder builder) {
this.HDD=builder.HDD;
this.RAM=builder.RAM;
this.isGraphicsCardEnabled=builder.isGraphicsCardEnabled;
this.isBluetoothEnabled=builder.isBluetoothEnabled;
}
//Builder Class
public static class ComputerBuilder{
// required parameters
private String HDD;
private String RAM;
// optional parameters
private boolean isGraphicsCardEnabled;
private boolean isBluetoothEnabled;
public ComputerBuilder(String hdd, String ram){
this.HDD=hdd;
this.RAM=ram;
}
public ComputerBuilder setGraphicsCardEnabled(boolean isGraphicsCardEnabled) {
this.isGraphicsCardEnabled = isGraphicsCardEnabled;
return this;
}
public ComputerBuilder setBluetoothEnabled(boolean isBluetoothEnabled) {
this.isBluetoothEnabled = isBluetoothEnabled;
return this;
}
public Computer build(){
return new Computer(this);
}
}
}
위와 같이 Computer 객체를 가져오려면 ComputerBuilder를 이용해야 합니다.
public class TestBuilderPattern {
public static void main(String[] args) {
Computer comp = new Computer.ComputerBuilder("500 GB", "2 GB")
.setBluetoothEnabled(true)
.setGraphicsCardEnabled(true)
.build();
}
}
다음과 같이 필요한 값만 set메소드를 활용하여 객체를 생성할 수 있습니다.
public class Posts {
@Id // 2.
@GeneratedValue(strategy = GenerationType.IDENTITY) // 3.
private Long id;
@Column(length = 500, nullable = false)
private String title;
@Column(columnDefinition = "TEXT", nullable = false)// 4.
private String content;
private String author;
@Builder // 7.
public Posts(String title, String content, String author) {
this.title = title;
this.content = content;
this.author = author;
}
}
다음과 같이 @Builder라는 어노테이션을 활용해 쉽게 빌더 패턴으로 클래스를 만들어 줄 수 있습니다.
postsRepository.save(Posts.builder() // 2.
.title(title)
.content(content)
.author("qweadzs@gmail.com")
.build());