빌더패턴
빌더 패턴이란 복합 객체의 생성 과정과 표현 방법을 분리하여 동일한 생성 절차에서 서로 다른 표현 결과를 만들 수 있게 하는 패턴이다.
코드를 보면서 알아보자.
YG형이 아래와 같이 블랙핑크를 만들었다. 생성자를 이용하고 있다.
public class YG {
public static void main(String[] args) {
Idol blankpink = new Idol("Blackpink", LocalDate.of(2016, 8, 8), "hiphop", "YG", Arrays.asList(
new Member("jisu", 27),
new Member("jenny", 26),
new Member("roje", 25),
new Member("lisa", 25)));
System.out.println(blankpink);
}
}
public class Idol {
private String name;
private LocalDate debut;
private String genre;
private String agency;
private List<Member> members;
public Idol(String name, LocalDate debut, String genre, String agency, List<Member> members) {
this.name = name;
this.debut = debut;
this.genre = genre;
this.agency = agency;
this.members = members;
}
public void addMembers(String name, int age) {
if (this.members == null) {
this.members = new ArrayList<>();
}
this.members.add(new Member(name, age));
this.setMembers(this.members);
}
}
YG형이 블랙핑크를 넘어서는 새로운 아이돌 "화이트핑크"를 계획중인데 데뷔일이랑, 멤버 구성을 아직 못 했다.
어떻게 새로운 아이돌을 만들 수 있을까?
[ 방법1 ] 사용하지 않는 인자는 null 값으로 채워서 생성한다.
YG형이 화를 낼 수 있다.🤬
"사용하지 않은 건 그냥 입력을 안 하게 해줘!! 귀찮아.. NULL을 몇 개를 쓰라는거야!?"
"난 멤버 정한적이 없는데, 누가 멤버 정했어!? 너가 사장해라."
생성자의 인자가 많거나, 옵션으로 선택적으로 사용되는 인자가 많은 경우 가독성이 좋지 못 하다.
그리고 추후에 사용하는 인자는 Setter를 사용해 수정해주기 때문에 immutable하지 못 하고, 사이드이펙트가 발생할 수 있고, 변경점을 찾기 어려워 유지보수가 어렵다.
public class YG {
public static void main(String[] args) {
Idol whitepink = new Idol("Whitepink", null, "hiphop", "YG", null);
System.out.println(whitepink);
}
}
방법2) 새로운 생성자 생성 - 사용하지 않는 인자는 받지 않고, 사용하는 인자만 받는 생성자를 추가한다.
YG형이 또 화를 낸다.🤬
"어떤 생성자를 써야 하는거야!? 2번째 인자로 장르를 넣어? 이름을 넣어? 뭐를 넣어야 하는거야!!!!!!!!!!!!"
옵셔널한 경우가 많아질 수록 클래스의 생성자가 많아져서 코드가 불필요하게 장황해지고, 가독성 악화는 물론 클라이언트도 사용하기 어려워진다.
public Idol(String name, String genre, String agency) {
this.name = name;
this.genre = genre;
this.agency = agency;
}
public class YG {
public static void main(String[] args) {
Idol whitepink = new Idol("Whitepink", "hiphop", "YG");
System.out.println(whitepink);
}
}
YG형이 많이 불편해 하신다...그리고 YG가 점점 성장할 수록 더 다양하게 아이돌을 생성할 텐데...
복잡도, 가독성, ... 유지보수가 점점 악화되겠다... 고치자.
필요한 데이터만 설정할 수 있게
유연성을 확보할 수 있게
가독성을 높일 수 있게
변경 가능성을 최소화하고 확장에는 열려있게
※ 빌더 패턴 적용하기
1. 빌더 만들기 - interface IdolBuilder를 만든다.
생성자의 인자별로 만들거나 함께 설정하는 인자는 묶어서 IdolBuilder를 리턴하는 메서드를 만든다.
최종 build메서드로 생성된 Idol을 리턴하도록 한다.
public interface IdolBuilder {
public IdolBuilder name(String name);
public IdolBuilder debut(LocalDate debut);
public IdolBuilder genre(String genre);
public IdolBuilder agency(String agency);
public IdolBuilder members(List<Member> members);
public Idol build();
}
2. concrete 빌더 만들기 - class DefaultIdolBuilder
콘크리트 클래스에서는 Idol 필드에, 빌더로 전달받은 인자를 설정한다.
public class DefaultIdolBuilder implements IdolBuilder {
private String name;
private LocalDate debut;
private String genre;
private String agency;
private List<Member> members;
@Override
public Idol build() {
return new Idol(name, debut, genre, agency, members);
}
@Override
public IdolBuilder agency(String agency) {
this.agency = agency;
return this;
}
@Override
public IdolBuilder debut(LocalDate debut) {
this.debut = debut;
return this;
}
@Override
public IdolBuilder genre(String genre) {
this.genre = genre;
return this;
}
@Override
public IdolBuilder members(List<Member> members) {
this.members = members;
return this;
}
@Override
public IdolBuilder name(String name) {
this.name = name;
return this;
}
}
3) 클라이언트 사용 - 설정하고 싶은 인자만 빌더로 딱딱 설정.
public class YG {
public static void main(String[] args) {
Idol blackpink = new DefaultIdolBuilder()
.name("Blackpink")
.debut(LocalDate.of(2016, 8, 8))
.genre("hiphop")
.agency("YG")
.members(Arrays.asList(
new Member("jisu", 27),
new Member("jenny", 26),
new Member("roje", 25),
new Member("lisa", 25)))
.build();
System.out.println(blackpink);
Idol whitepink = new DefaultIdolBuilder()
.name("Whitepink")
.genre("hiphop")
.agency("YG")
.build();
System.out.println(whitepink);
}
}
빌더 패턴의 장점
- 필요한 데이터만 설정할 수 있다.
- 유연성을 확보할 수 있다.
- 가독성을 높일 수 있다.
- 변경 가능성을 최소화하고 확장에는 열려있게 할 수 있다
빌더 패턴의 단점
- 단점보다는 빌더 패턴이 필요없는 예외적인 케이스가 있다.
- 객체 생성을 라이브러리로 위임하는 경우
- 생성자 인자의 개수가 2개 이하이며, 변경 가능성이 없는 경우
'Develop > Fundmental' 카테고리의 다른 글
Bridge Pattern(브릿지 패턴) (0) | 2022.05.01 |
---|---|
Adapter Pattern (어댑터 패턴) (0) | 2022.05.01 |
팩토리 패턴(Factory Pattern) (0) | 2022.04.26 |
싱글톤 패턴(Singleton Pattern) (0) | 2022.04.24 |
[cmd] 사용중인 포트 PID 찾기(netstat option) (0) | 2021.10.16 |
댓글