-
item 2 생성자에 매개변수가 많다면 빌더를 고려하라책/이펙티브 자바 2022. 2. 10. 20:47
ITEM 2 생성자에 매개변수가 많다면 빌더를 고려하라
정적 팩터리 패턴과 생성자는 매개변수가 많을 때 가독성이 떨어지게 된다
이럴때 점층적 생성자 패턴, 자바 빈즈 패턴, 빌더 패턴을 사용해보자
점층적 생성자 패턴
public class Foo { private String userName; //필수값 private int age; //필수값 private String address; //필수값 private String tel; //선택값 public Foo(String userName) { this.userName = userName; } public Foo(String userName, int age) { this.userName = userName; this.age = age; } public Foo(String userName, int age, String address) { this.userName = userName; this.age = age; this.address = address; } public Foo(String userName, int age, String address, String tel) { this.userName = userName; this.age = age; this.address = address; this.tel = tel; } }
장점
- 매개변수의 개수에 따라 생성자가 점점 증가하는 방식이다
- 한번의 호출로 객체가 생성된다
단점
- 매개변수가 증가함에 따라 각 값의 순서나 개수등을 신경 써야한다
- 한눈에 의미를 파악하기가 어렵고 호출부의 가독성이 떨어지고 작성하기가 어려워진다
- 필수값이 아닌 값이라도 객체 생성을 위해 빈 값을 넣어줘야 한다
public static void main(String[] args) { Foo foo = new Foo("hong"); Foo foo2 = new Foo("hong",10); Foo foo3 = new Foo("hong",10,"대전"); Foo foo4 = new Foo("hong",10,"대전",""); }
자바 빈즈 패턴
public class FooJavaBeans { private String userName; private int age; private String address; private String tel; public void setUserName(String userName) { this.userName = userName; } public void setAge(int age) { this.age = age; } public void setAddress(String address) { this.address = address; } public void setTel(String tel) { this.tel = tel; } }
장점
- 기본 생성자 하나만 만들고 set 메서드를 통하여 값을 셋팅해준다
- 점층적 생성자 패턴보다 가독성이 좋다
- 점층적 생성자 패턴보다 확장하기가 편하다
단점
- 한번의 호출로 객체 생성이 끝나지 않기 때문에 일관성이 무너진 상태가 된다
- setter가 존재 하기에 불변으로 만들수 없어 쓰레드 안정성을 위해 추가적인 작업이 필요하다
- 점층적 생성자 패턴과 다르게 매개변수의 유효성 체크가 즉각적으로 이루어지지 않는다
public static void main(String[] args) { FooJavaBeans fooJavaBeans = new FooJavaBeans(); fooJavaBeans.setUserName("hong"); fooJavaBeans.setAge(10); fooJavaBeans.setAddress("대전"); fooJavaBeans.setTel(""); }
빌더 패턴
package chapter2.item2; public class FooBuilder { private final String userName; private final int age; private final String address; private final String tel; public static class Builder { private final String userName; //필수값 private final int age; //필수값 private final String address; //필수값 private String tel; //선택값 public Builder(String userName, int age, String address) { this.userName = userName; this.age = age; this.address = address; } public Builder tel(String tel) { this.tel = tel; return this; } public FooBuilder build() { return new FooBuilder(this); } } private FooBuilder(Builder builder) { userName = builder.userName; age = builder.age; address = builder.address; tel = builder.tel; } }
장점
- 점층적 생성자 패턴과 자바 빈 패턴의 장점을 합쳤다(불변성 + 가독성)
- 호출부 코드를 메서드 체이닝으로 작성하여 가독성이 좋아졌다
- 점층적 생성자 패턴처럼 객체의 일관성도 보장되며 객체 생성시 필수값 지정도 가능하다
- 빌더 하나로 여러 객체를 순회하며 만들 수 있다
- 매개변수에 따라 다른 객체를 생성 할수도 있으므로 유연성이 높다
단점
- 클래스 내부에 빌더를 추가로 만들어 주는 작업이 필요하기 때문에 필수 매개변수가 많다면 생각이 좀 필요하다
- 어쨋거나 빌더를 추가로 만드는 것익이 때문에 성능에 민감하다면 생각을 좀 해봐야 한다
public static void main(String[] args) { FooBuilder fooBuilder = new FooBuilder.Builder("hong",10,"대전") .tel("01012345678") .build(); }
불변(immutable) 과 불변식(invariant)
- 불변
- 변경을 할수 없다는 뜻, 대표적으로 String이 있다
- 불변식
- 프로그램이 실행중, 정해진 일정 기간동안 만족해야 하는 조건이다
- 변경 허용이 가능하지만 특정 조건내에서만 가능하다
생성자의 매개변수가 늘어나는 경우가 빈번하니 추후 확장성을 위해 처음부터 빌더로 생성 하는걸 고려 해보자
'책 > 이펙티브 자바' 카테고리의 다른 글
item 6 불필요한 객체 생성을 피하라 (0) 2022.02.16 item 5 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) 2022.02.15 item 4 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) 2022.02.14 item 3 private 생성자나 열거 타입으로 싱글턴임을 보증하라 (0) 2022.02.11 item 1 생성자 대신 정적 팩터리 메서드를 고려하라 (0) 2022.02.09