2021. 8. 2. 01:05ㆍ이펙티브 자바 정리
생성자 대신 정적 팩터리 메서드를 고려하라
public static Boolean valueOf(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
- 클래스는 클라이언트에 public 생성자 대신(혹은 생성자와 함께) 정적 팩토리 메서드를 제공할 수 있다.
- 장점
- 이름을 가질 수 있다.
- 호출될 때마다 인스턴스를 새로 생성하지는 않아도 된다.
- 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다. (이 능력은 반환할 객체의 클래스를 자유롭게 선택할 수 있게 하는 ' 엄청난 유연성을 가진다.')
- 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환 할 수 있다. (클라이언트는 팩터리가 건네주는 객체가 어느 클래스의 인스턴스인지 알 수도 없고 알 필요도 없다.)
- 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
- 단점
- 상속을 하려면 public이나 protected 생성자가 필요하니 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.
- 정적 팩토리 메서드는 프로그래머가 찾기 어렵다.
- 정리
- 정적 팩토리 메서드와 public 생성자는 각자의 쓰임새가 있으니 상대적인 장단점을 이해하고 사용하는 것이 좋다. 그렇다고 하더라도 정적 팩토리를 사용하는 게 유리한 경우가 많으므로 무작정 public 생성자를 제공하던 습관이 있다면 고치자!!!
- 장점
생성자에 매개변수가 많다면 빌더를 고려하라
- 정적 팩토리와 생성자에는 똑같은 제약이 하나 있다. 선택적 매개변수가 많을 때 적절히 대응하기 어렵다는 점이다. 그래서 프로그래머들은 이럴 때 점층적 생성자 패턴을 즐겨 사용했다. 필수 매개변수만 받는 생성자, 필수 매개변수와 선택 매개변수 1개를 받는 생성자, 선택 매개변수를 2개까지 받는 생성자, 선택 매개변수를 전부 다 받는 생성자까지 늘려가는 방식이다.
public class NutriFacts {
private final int servingSize; // 1회 제공량 필수
private final int servings; // n회 제공량 필수
private final int calories; // 1회 제공량당 선택
private final int fat; //1회 제공량 선택
private final int sodium; //1회 제공량 선택
private final int carnogydrate; //1회 제공량 선택
}
public NutriFacts(int servingSize, int servings) {
this(servingSize, servings, 0);
}
public NutriFacts(int servingSize, int servings, int calories) {
this(servingSize, servings, calories, 0);
}
public NutriFacts(int servingSize, int servings, int calories, int fat, int sodium, int carbohydrate) {
this.servingSize = servingSize;
this.servings = servings;
this.calories = calories;
this.fat = fat;
this.sodium = sodium;
this.carbohydrate = carbohydrate;
}
- 이러한 점층적 생성자 패턴도 쓸 수는 있지만, 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기가 어렵다.
빌더 패턴
public class NuritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
//필수 매개변수
private final int servingSize;
private final int servings;
//선택 매개변수 - 기본값으로 초기화한다.
private int calories = 0;
private int fat = 0;
private int sodium = 0;
private int carbohydrate = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {this.calories = val; return this;}
public Builder fat(int val) {this.fat = val; return this;}
public Builder sodium(int val) {this.sodium = val; return this;}
public Builder carbohydrate(int val) {this.carbohydrate = val; return this;}
public NuritionFacts build() {
return new NuritionFacts(this);
}
}
private NuritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
- NutritionFacts 클래스는 불변이며, 모든 매개변수의 기본값들을 한 곳에 모아 뒀다. 이런 방식을 메서드 호출이 흐르듯 연결된다는 뜻으로 플루언트API or 메서드 연쇄라고 한다.NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).calories(100).sodium(35).carbohydrate(27).build();
'이펙티브 자바 정리' 카테고리의 다른 글
이펙티브 자바 정리 2일차 (0) | 2021.08.11 |
---|