-
이펙티브 자바 - ITEM2⏰ 오늘의 공부/Java 2022. 1. 5. 01:51
많은 Parameter가 있는 Constructor 는 Builder를 고려하라
ex) 클래스에서 여러 파라미터 중 반드시 필요한 파라미터가 있고 없어도 되는 파라미터가 있다.
public class NutritionFacts { private final int servingSize; // 1회 제공량 (need) private final int servings; // 총 n회 제공량 (need) private final int calories; // 1회 제공량당 (need) private final int fat; // g/1회 제공량 (option) private final solium; // mg/1회 제공량 (option) private final carbohydrate; // g/1회 제공량 (option) }
적절하게 대응하기 위한 방안
- 여러 개의 Constructor를 둔다.
public NutritionFacts(int servingSize, int servings, int calories) { this.servingSie = servingSize; this.servings = servings; this.calories = calories; } public NutritionFacts(int servingSize, int servings, int calories, int fat) { this.servingSie = servingSize; this.servings = servings; this.calories = calories; this.fat = fat; } public NutritionFacts(int servingSize, int servings, int calories, int solium) { this.servingSie = servingSize; this.servings = servings; this.calories = calories; this.solium = solium; } // ...
- 타입과 인자의 순서를 바꾸는 실수를 하게 되면 오류를 찾기 매우 어려울 수 있다.
- 가독성 좋지 않다.
- Java Beans Pattern 사용
- 매개변수가 없는 생성자로 객체를 생성한 후에 수정자(setter) 메서드를 호출해서 값을 채우는 것
public NutritionFacts() {} public void setServingSize(int servingSize) { this.servingSize = servingSize; } public void setServing(int servings) { this.servings = servings; } public void setCalories(int calories) { this.calories = calories; } // ... // 실제 객체 생성할 때 public void someMethod() { NutritionFacts nutritionFacts = new NutritionFacts(); nutritionFacts.setServingSize(3); nutritionFacts.setServing(1); nutritionFacts.setCalories(100); ... }
- 1회의 메서드 호출로 객체 생성을 완료할 수 없게 된다.
- 객체의 일관성(consistency)이 무너짐 / 변경 불가능(immutable)한 클래스를 만들 수 없게 된다.
- 매개변수가 없는 생성자로 객체를 생성한 후에 수정자(setter) 메서드를 호출해서 값을 채우는 것
- 빌더 패턴 사용
- 필요한 객체를 직접 만드는 것이 아니라 필수 매개변수만으로 생성자를 호출하여 빌더 객체를 얻고 수정자(setter) 역할을 하는 메서드들을 연쇄적으로 호출하여 원하는 매개변수를 설정
- 마지막으로 build 메서드를 호출하여 immutable한 객체를 얻는다.
점층적인 생성자 패턴의 안정성과 자바빈 패턴의 가독성을 함께 가질 수 있다.public class NutritionFacts { private final int servingSize; // 1회 제공량 (need) private final int servings; // 총 n회 제공량 (need) private final int calories; // 1회 제공량당 (need) private final int fat; // g/1회 제공량 (option) public static class Builder { private final int servingSize; private final int servings; private final int calories; private int fat; public Builder(int servingSize, int servings, int calories) { this.servingSize = servingSize; this.servings = servings; this.calories = calories; } public Builder fat(int val) { this.fat = val; return this; } public NutritionFacts build() { return new NutritionFacts(this); } } private NutritionFacts(Builder builder) { this.servingSize = builder.servingSize; this.servings = builder.servings; this.calories = builder.calories; this.fat = builder.fat; } } // 사용방법 NutritionFacts builder = new NutritionFacts.Builder(240, 9, 100).setFat(3).build();
- 단점
- Builder를 항상 만들어야 하기 때문에 생성 비용이 무조건 생긴다.
- 점층적 생성자 패턴보다 장황하여 적은 갯수의 파라미터일 경우 오히려 좋지 않을 수 있다.
'⏰ 오늘의 공부 > Java' 카테고리의 다른 글
이펙티브 자바 - ITEM1 (0) 2022.01.05 - 여러 개의 Constructor를 둔다.