-
[Effective Java 공부하기] 2. 생성자에 매개변수가 많다면 빌더를 고려하라Java 2022. 3. 29. 00:12반응형
생성자에 매갭변수가 많다면 빌더를 고려하라
클래스의 인스턴스를 생성하기 위해서 생성자를 이용하는 것이 일반적이다.
Student student = new Student(1L, "장규민", 10);
생성자의 매개변수가 예시처럼 간단할 때는 생성자를 통한 인스턴스 생성 방법은 좋은 선택이 될 수 있지만 10개가 넘는 생성자 매개변수가 존재하고 매개변수의 타입마저 연달아 늘어서 있다면 코드를 작성할 때 휴먼에러로 이러질 수 있다.
특히, 매개변수의 타입이 같아서 개발자가 실수한다면 컴파일 시, 오류를 잡아내지 못하기에 한참동안 방황할 수도 있을 것 같다.
// 매개변수가 많아져 눈에 들어오지 않는다. Student student = new Student(1L, "장규민", 10, 179, 71, 100, 234, "01099700790", 12034, 634, 1234, 623, 1234, 523, 524);
물론 원하는 속성의 값만 초기화 하기 위해 점층적 생성자 패턴을 사용하여 생성자 매개변수를 줄일수도 있다.
// 초기화를 원하는 속성을 점층적 생성자 패턴 public Student(Long studentId, String name, int height, int weight) { this.studentId = studentId; this.name = name; this.height = height; this.weight = weight; } Student student = new Student(1L, "장규민", 179, 71);
하지만 이마저의 매개변수도 길어질 여지는 충분히 있다.
JavaBeans Pattern
생성자 방법의 첫번째 대안으로는 자바빈즈 패턴(JavaBeans pattern)이 있다. 우리가 익숙하게 사용하는
Getter
,Setter
메서드를 통해 인스턴스 속성에 접근하고 변경할 수 있다.public class Student { private Long studentId; private String name; private int age; private int height; private int weight; private String phoneNo; public Student() { } public Long getStudentId() { return studentId; } public void setStudentId(Long studentId) { this.studentId = studentId; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public int getHeight() { return height; } public void setHeight(int height) { this.height = height; } public int getWeight() { return weight; } public void setWeight(int weight) { this.weight = weight; } public String getPhoneNo() { return phoneNo; } public void setPhoneNo(String phoneNo) { this.phoneNo = phoneNo; } }
Student s = new Student(); s.setStudentId(1L); s.setName("장규민");
매개변수가 길게 나열된 생성자 패턴보다는
Setter
메서드를 통해 필요한 속성에 직접 값을 설정할 수 있으므로 직관적으로 보인다. 하지만 Effective Java 에서는 하나의 객체를 만드는데 여러개의 메서드가 호출되어야 하고 객체가 완전히 생성되기 전까지 일관성(consistency)가 무너진 상태로 놓이기에 큰 단점이 될 수 있다고 한다. 이 말은 즉슨 메서드의 호출을 이용한 객체 속성의 설정은 소스 이곳저곳에서 사용될 우려가 있어 런타임 오류 시, 디버깅이 매우 힘든다는 것이다. 때문에 실제로 운영되는 서비스에서는Setter
메서드의 사용을 최대한 자제하기도 한다.
Builder Pattern
- 점측적 생성자 패턴의 안전성 + 자바빈즈 패턴의 가독성
- 불변의 클래스
public class Student { private Long studentId; private String name; private int age; private int height; private int weight; private String phoneNo; public Student(Builder builder) { studentId = builder.studentId; name = builder.name; age = builder.age; height = builder.height; weight = builder.weight; phoneNo = builder.phoneNo; } public static class Builder { private Long studentId; private String name; private int age = 0; private int height = 0; private int weight = 0; private String phoneNo = null; public Builder studentId(Long studentId) { this.studentId = studentId; return this; } public Builder name(String name) { this.name = name; return this; } public Builder age(int age) { this.age = age; return this; } public Builder height(int height) { this.height = height; return this; } public Builder weight(int weight) { this.weight = weight; return this; } public Builder phoneNo(String phoneNo) { this.phoneNo = phoneNo; return this; } public Student builder() { return new Student(this); } } } public class Main { public static void main(String[] args) { // 플루언트(fluent) API 또는 메서드 연쇄(method chaining) new Student.Builder() .studentId(1L) .name("장규민") .height(182) .weight(120) .builder(); } }
반응형'Java' 카테고리의 다른 글
[Effective Java 공부하기] 6. 불필요한 객체 생성을 피하라 (0) 2022.04.01 [Effective Java 공부하기] 4. 인스턴스화를 막으려거든 private 생성자를 사용하라 (0) 2022.03.31 [JAVA] 정규표현식 정리하기(); (0) 2021.06.29 [Java] 제네릭 타입 정리하기(); (0) 2021.04.25 [Java] Collection 프레임워크(List, Set, Map) (0) 2020.03.04