티스토리 뷰
정적 팩터리 메서드와 생성자는 선택적 매개변수가 많을 때 적절히 대응하기 어렵다는 단점이 있다.
💡 대안 1 : 자바빈즈 패턴 (JavaBeans Pattern)
매개변수가 없는 생성자로 객체를 만든 후, setter
메소드를 호출해 매개변수의 값을 설정한다.
public class KongGookSoo {
String name;
String address;
String kindOfBeans;
boolean isAlways;
int price;
// getter, setter..
}
KongGookSoo kgs = new KongGookSoo();
kgs.setName("서민준밀밭");
kgs.setAddress("서울시 영등포구");
kgs.setKindOfBeans("대두");
kgs.setIsAlways(true);
kgs.setPrice(11000);
👍 장점
- 인스턴스를 만들기 쉽다.
- 읽기 편하다
👎 단점
- 객체 하나를 만들기 위해 여러 메서드를 호출해야 한다.
- 객체를 완성하기 전까지는 일관성이 무너진 상태에 놓인다.
- 클래스를 불변으로 만들 수 없으며, 스레드 안정성을 얻기 위한 추가 작업이 필요하다.
💡 대안 2 : 빌더 패턴 (Builder Pattern)
필수 매개변수만으로 생성자(혹은 정적 팩터리)를 호출해 빌더 객체를 얻는다.
그 다음 빌더 객체가 제공하는 setter
메소드를 호출해 매개변수를 설정한다.
public class KongGookSoo {
private final String name;
private final String address;
private final String kindOfBeans;
private final boolean isAlways;
private final int price;
public static class Builder {
// 필수 매개변수
String name;
String address;
boolean isAlways;
// 선택매개변수 - 기본값
String kindOfBeans = "";
int price = 0;
public Builder(String name, String address, boolean isAlways) {
this.name = name;
this.address = address;
this.isAlways = isAlways;
}
public Builder kindOfBeans(String kindOfBeans) {
this.kindOfBeans = kindOfBeans;
return this;
}
public Builder price(int price) {
this.price = price;
return this;
}
public KongGookSoo build() {
return new KongGookSoo(this);
}
}
private KongGookSoo(Builder builder) {
name = builder.name;
address = builder.address;
kindOfBeans = builder.kindOfBeans;
isAlways = builder.isAlways;
price = builder.price;
}
}
KongGookSoo kgs = new KongGookSoo.Builder("콩심팥심", "경기도 김포시", true).kindOfBeans("대두").price(10000).build();
연쇄적으로 호출되므로 플루언트API, 메서드 연쇄(method chaining)이라고도 한다.
계층적으로 설계된 클래스와 함께 쓰기 좋다.
public abstract class Game {
public enum Genre { FPS, RACING, RPG, SIMULATION, SPORTS, TACTIC }
final Set<Genre> genres;
abstract static class Builder<T extends Builder<T>> {
EnumSet<Genre> genres = EnumSet.noneOf(Genre.class);
public T addGenre(Genre genre) {
genres.add(Objects.requireNonNull(genre));
return self();
}
abstract Game build();
protected abstract T self();
}
Game(Builder<?> builder) {
genres = builder.genres.clone();
}
}
이것은 게임의 장르를 표현하는 계층구조의 루트에 놓인 추상클래스이다.
public class Overwatch extends Game{
public enum Client { BLIZZARD, STEAM }
private final Client client;
public static class Builder extends Game.Builder<Builder> {
private final Client client;
public Builder(Client client) {
this.client = Objects.requireNonNull(client);
}
@Override
Overwatch build() {
return new Overwatch(this);
}
@Override
protected Builder self() {
return this;
}
}
private Overwatch(Builder builder) {
super(builder);
client = builder.client;
}
}
public class StardewValley extends Game {
private final boolean isVanila;
public static class Builder extends Game.Builder<Builder> {
private boolean isVanila = true; // 기본값
public Builder vanila() {
isVanila = true;
return this;
}
@Override
StardewValley build() {
return new StardewValley(this);
}
@Override
protected Builder self() {
return this;
}
}
private StardewValley(Builder builder) {
super(builder);
isVanila = builder.isVanila;
}
}
Overwatch overwatch = new Overwatch.Builder(Overwatch.Client.BLIZZARD)
.addGenre(Game.Genre.FPS).addGenre(Game.Genre.TACTIC)
.build();
StardewValley stardewValley = new StardewValley.Builder()
.addGenre(Game.Genre.SIMULATION).addGenre(Game.Genre.RPG)
.vanila()
.build();
- 각 하위 클래스의 빌더가 정의한
builder
메서드는 해당 구체 하위 클래스를 반환하도록 선언한다.Overwatch.Builder
는Overwatch
반환,StardewValley.Bulider
는StardewValley
반환- 이것을 공변환 타이핑 (Convariant Return Typing) 이라고 한다.
- 클라이언트가 형변환에 신경쓰지 않고 빌더를 사용할 수 있다.
👎 단점
객체를 만들기 앞서 빌더부터 만들어야 한다.
매개변수가 4개 이상은 되어야 값어치를 한다. (그러나 API는 시간이 지날수록 매개변수가 많아지는 경향이 있다.)
'Java > 이펙티브 자바' 카테고리의 다른 글
[아이템 1] 생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2023.10.23 |
---|
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- ORA-02289
- 프로그래머스
- BuilderPattern
- 이진트리
- 정적팩터리메서드
- 투포인터 #알고리즘
- 알고리즘
- 탐욕법
- 전위순회
- 분리집합
- Sequence
- 시퀀스가존재하지않습니다
- 생성자
- Java
- 여행가자
- greedy
- 트리순회
- 스레드
- 후위순회
- 중위순회
- deque
- 시퀀스
- 이펙티브자바
- 백준1976
- 백준
- 빌더패턴
- BAEKJOON
- 자바
- 유니온파인드
- effectivejava
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
글 보관함