Whiteship's Note


EJ2E Item 2. 생성자에 매개변수가 너무 많을 때는 빌더를 고려하자.

Java : 2008.10.27 18:20


참조: Effective Java 2nd Edition. Item 2: Consider a builder when faced with many constructor parameters

생성자나 static factory method에 매개 변수가 너무 많고 다양할 때 기존에는 Telescoping constructor 패턴 또는 JavaBeans 패턴을 사용왔다.

telescoping constructor 패턴
- 생성자에서 다른 생성자 호출하면서 비는 매개변수에는 기본값 설정해주는 방식.
- 잘 동작은 하는데, 매개 변수를 많이 사용할 떄는 클라이언트 코드를 작성하기도 힘들고, 읽기도 힘들다.
- 위치가 바껴도 컴파일 에러가 안 남.
 
JavaBeans 패턴
- 기본 생성자만 사용하고, 필요한 속성은 세터 사용.
- 쉽게 객체 생성 가능. 코드 읽기 쉬움.
- 생성 과정이 여러 호출로 구성되어 있어서 불완전한 상태로 사용될 여지가 있다.
- 불변 객체로 만드는 걸 불가능하게 하고, 쓰레드 세이프티를 보장하려면 개발자가 추가로 신경을 써야 한다. -> freezing 이용할 수 있지만 이 방법은 거의 사용 안 해.

Builder 패턴
- 필요한 객체를 직접 만들지 않고, 필수 매개 변수를 생성자나 static factory 메소드에 넘겨서 객체를 만들고, 부가적인 속성들은 그 뒤에 설정한다. 그리고 최종적으로 build()를 호출해서 불변 객체를 생성한다.
- 클라이언트 코드
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
- 작성하기도 쉽고, 읽기도 쉽다. Ada와 Python의 named optional parameters를 사용했다.
- Abstract Factory 패턴을 구현할 때, 자바 1.5 이상의 버전에서 빌더를 사용하면, 예전처럼 런타임이 아닌 컴파일 타임에 에러를 발견할 수 있다.
- 단점: 빌더 객체 생성 비용. 다른 패턴에 비해서 좀 복잡하다. 따라서 매개 변수가 넷 이상일 때만 사용을 권장.
top


EJ2E Item 1. 생성자 대신 static 팩토리 메소드 사용을 고려하라.

Java : 2008.10.27 17:52


참조: Effective Java 2nd Edition. Item 1: Consider static factory methods instead of constructor

static factory method는 Factory Method 디자인 패턴이랑 같은 것이 아니다. 직접적인 관계는 없다.

장점
- 이름을 가질 수 있다.
- 매번 새로운 객체를 만들 필요가 없어진다.
- 하위 타입을 반환할 수 있다. -> service provider framework
- 타입 매개변수를 가진 클래스 객체를 생성할 때 간결하게 쓸 수 있다. -> type inference

Service Provider Framework
- Servide interface: 공급자가 구현할 인터페이스. ex) Connection
- Provider registration API: 시스템이 구현체를 등록할 때 사용. ex) DriverManager.registerDriver
- Service access API: 사용자가 서비스 객체를 얻어올 때 사용. == fexible static factory. ex) DriverManager.getConnection
- (option) Service provider interface: 공급자가 서비스 구현체의 객체를 생성할 때 구현한다. ex) Driver

단점
- public 또는 protected 생성자 없이 static factory method만 제공하는 클래스는 상속할 수 없다.
- 다른 static factory method랑 확연하게 구분이 안 된다. -> 이름을 잘 짓자.(valueOf, of, getInstance, newInstance, getType, newType)

top