먼저, 생성 패턴 중 하나인 builder 패턴에 대해서 알아보도록 하겠습니다!
build라는 영어의 뜻에서도 이 패턴을 왜 사용하는지 추측해볼 수도 있습니다.
build는 구조를 갖춘 구조물을 짓다
를 의미합니다.
구조물을 짓기 위해서는 매우 복잡한 과정을 차례 차례 수행해야합니다.
따라서, builder 패턴은 복잡한 객체의 생성 과정을 위해서 만들어진 패턴입니다.
여기에서 가장 주목해야 하는 것은 Director 클래스
입니다.
위의 builder 패턴 다이어 그램에서 client는 director 클래스를 사용해서, 단지 construct 메소드만 호출하면, director 클래스가 알아서 복잡한 과정(buildPart1, buildPart2)를 수행해서 인스턴스를 만들어줍니다.
이처럼 director 클래스는 builder의 복잡도를 낮추기 위한 것입니다.
따라서, 복잡도가 높은 로직을 만들 때에는 builder 패턴을 사용하면 client가 쉽게 사용할 수 있어서 유용하게 사용됩니다.
public class Director {
private Builder builder;
//생성자
public Director(Builder builder) {
//Builder 클래스는 추상 클래스 -> 인스턴스 생성 X
//Director의 생성자에 실제로 전달되는 것 = Builder의 하위 클래스의 인스턴스
this.builder = builder;
}
public void construct() {
builder.builPart1("Greeting");
builder.buildPart2("일반적인 인사");
}
}
public class Main {
public static void main(String[] args) {
Builder b = (Builder) o;
Director director = new Director(b);
director.construct();
}
}
위의 패턴과 동일한 이름을 가진 스프링 부트의 어노테이션이 있습니다.
여기에서 언급하는 GoF의 디자인 패턴 중 Builder 패턴과 완벽하게 동일하지는 않지만, 해당 이름과 연관성이 있습니다.
먼저, @Builder 어노테이션
을 주로 사용하는 이유에 대해서 언급해 보겠습니다.
@Builder 어노테이션은 클래스의 선택적 매개변수가 많은 상황에서 가장 유용하게 사용됩니다.
아래의 코드처럼 여러 속성값이 가지고 있는데, 인스턴스 생성시에 어떤 속성값은 들어가야 하고, 안 들어가는 속성값을 따로 명시해줘야 하는 경우 여러 생성자를 명시해주기 어렵습니다.
@Builder
public class Person {
private String username;
private int age;
private String area;
private String phoneNumber;
private Long money;
private int cars;
}
따라서 @Builder 어노테이션을 사용하면, 아래의 코드처럼 자동적으로 여러 생성자를 생성해줍니다.
만약에, username을 지정해주지 않더라도 해당 값을 제외한 생성자를 사용할 수 있습니다.
public class Person {
private String username;
private int age;
private String area;
private String phoneNumber;
private Long money;
private int cars;
Person(String username, int age) {
this.username = username;
this.age = age;
}
public static Person.PersonBuilder builder() {
return new BuildMe.BuildMeBuilder();
}
//Builder 클래스
public static class PersonBuilder {
private String username;
private int age;
BuildMeBuilder() {
}
public Person.PersonBuilder username(String username) {
this.username = username;
return this;
}
public Person.PersonBuilder age(int age) {
this.age = age;
return this;
}
public Person.PersonBuilder area(String area) {
this.area = area;
return this;
}
public Person.PersonBuilder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public Person.PersonBuilder money(Long money) {
this.money = money;
return this;
}
public Person.PersonBuilder cars(int cars) {
this.cars = cars;
return this;
}
public Person build() {
return new Person(this.username, this.age, this.area, this.phoneNumber, this.money, this.cars);
}
}
}
이와 같이 속성값이 많은 것도 복잡도가 높다는 측면에서 보면, 속성값이 많은 클래스의 인스턴스를 쉽게 생성해주기 때문에 복잡도가 높은 클래스를 사용하기 편리하게 만들어 줍니다.