문제점
Class를 정의하고 각 상황에 필요한 변수를 넣어 생성자를 생성하게 되거나 기본생성자로 인스턴스 생성 후 setter로 변수에 값을 주게 되면 관리가 힘들어진다.
public class Person {
private String name;
private String nickname;
private int age;
private int height;
private int weight;
public Person(){}
public Person(String name, int age, int height, int weight){
this.name = name;
this.age = age;
this.height = height;
this.weight = weight;
}
public Person(String nickname, int height, int weight){
this.name = nickname;
this.height = height;
this.weight = weight;
}
public void setName(String name) {
this.name = name;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public void setAge(int age) {
this.age = age;
}
public void setHeight(int height) {
this.height = height;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Person a = new Person("mson", 181, 87);
Person b = new Person();
b.setNickname("mson");
b.setHeight(181);
b.setWeight(87);
여기서 만약 필수로 들어가야하는 변수가 늘어나는 경우 다시 setter로 해당 변수를 설정해주거나 생성자들을 수정해 주어야 한다. 이를 해결하고자 Builder pattern을 사용한다.
구현
구현 부분은 해당 클래스에 @Builder 어노테이션을 붙이고 빌드한 결과 코드를 가져왔다.
public class Person {
private String name;
private String nickname;
private int age;
private int height;
private int weight;
Person(final String name, final String nickname, final int age, final int height, final int weight) {
this.name = name;
this.nickname = nickname;
this.age = age;
this.height = height;
this.weight = weight;
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String name;
private String nickname;
private int age;
private int height;
private int weight;
PersonBuilder() {
}
public PersonBuilder name(final String name) {
this.name = name;
return this;
}
public PersonBuilder nickname(final String nickname) {
this.nickname = nickname;
return this;
}
public PersonBuilder age(final int age) {
this.age = age;
return this;
}
public PersonBuilder height(final int height) {
this.height = height;
return this;
}
public PersonBuilder weight(final int weight) {
this.weight = weight;
return this;
}
public Person build() {
return new Person(this.name, this.nickname, this.age, this.height, this.weight);
}
Person a = new Person.builder()
.nickname("mson")
.weight(181)
.height(87)
.build();
사용할때는 이런식으로 Builder를 통해 기본생성자를 생성후 필요한 속성들을 해당 메소드로 설정해주면 된다. 만약 인스턴스를 생성할 때 필수적으로 필요한 변수들이 있다면 밑에 방법으로 빌더 생성자를 고쳐주면 된다.
public class Person {
private String name;
private String nickname;
private int age;
private int height;
private int weight;
Person(final String name, final String nickname, final int age, final int height, final int weight) {
this.name = name;
this.nickname = nickname;
this.age = age;
this.height = height;
this.weight = weight;
}
public static PersonBuilder builder(String nickname) {
return new PersonBuilder(String nickname);
}
public static class PersonBuilder {
private String name;
private String nickname;
private int age;
private int height;
private int weight;
PersonBuilder(String nickname) {
this.nickname = nickname;
}
...
}
Person a = new Person.builder("mson")
.weight(181)
.height(87)
.build();
Person b = new Person.builder() // 기본 생성자가 수정되어 nickname값을 넣지않고 인스턴스를 생성하면 오류가 난다.
.nickname("mson")
.weight(181)
.height(87)
.build();
스프링에서 @Builder 패턴을 사용할 때는 필수 변수를 따로 설정해 줄 수 있는 방법이 없기 때문에 필수 변수를 사용하려면 위에 코드처럼 build 코드를 가져온 후 수정하여 커스텀하여야 한다.
장점
- 불필요한 생성자를 제거하고 쉽고 직관적으로 인스턴스 생성이 가능하다
- 클래스 변수를 확장하기 쉽다.
- 가독성이 높고 코드가 유연해진다.
단점
- 관리해야 하는 클래스의 수가 늘어난다.
- 클래스 변수가 적을 경우 효과를 보기 힘들다.
- 성능에 약간의 영향을 주기 떄문에 성능에 민감한 프로그램일 경우 잘 고려하고 설계해야 한다.
'디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 템플릿 메서드 패턴(Template Method Pattern) (0) | 2023.02.24 |
---|---|
[디자인 패턴] 팩토리 메서드 패턴(Factory Method Pattern) (0) | 2023.02.22 |
[디자인 패턴] 싱글톤 패턴(Singleton pattern) (0) | 2023.02.14 |