effective java 객체 생성과 파괴
Item 2 - 생성자에 매개변수가 많다면 빌더를 고려해라.
- 점층적 생성자 패턴을 즐겨 사용했다. 선택 매개변수를 늘려가는 식으로 생성자를 만들게 된다.
- 점층적 생성자 패턴을 쓸 수 도 있지만, 매개변수 개수가 많아지면 클라이언트 코드를 작성하거나 읽기 어렵다.
- 자바 빈즈 패턴에서는 객체 하나를 만들려면 메서드를 여러 개 호출해야 하고, 객체가 완전히 생성되기 전까지는 일관성이 무너진 상태에 놓인다.
- 자바 빈즈 패턴에서는 클래스를 불변으로 만들 수 없다.
- 아래 처럼 호출이 흐르듯 연결되는것이 플루언트 API 라고 한다.
public class NutritionFacts {
private final int servingSize;
public static class Builder {
//필수 매개변수
private final int servingSize;
//선택 매개변수
private int calories = 0;
public Builder(int servingSize, int servings){
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val){
calories = val;
return this;
}
public Builder fat(itn val){
fat = val;
return this;
}
public Builder sodium(int val){
sodium = val;
return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
private NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
...
}
}
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8)
.calories(100).sodium(35).carbohydrate(27).build();
- 하위 클래스의 메서드가 상위 클래스의 메서드가 정의한 반환 타입이 아닌 그 하위 타입을 반환하는 기능을
공변 반환 타이핑
이라 한다.- 빌더 패턴이라고 사용했지만 오버라이드의 이점을 본것이 아닌지?
상우 타입의 클래스 중 아래 부분을 오버라이드 하게 된다. 코에 걸면 코걸이 기분인데..? abstract static class Builder<T extends Builder<T>>{ ... abstract Pizza build(); protected abstract T self(); }
- NyPizza.Builder > NyPizza
- Calzone.Builder > Calzone
@Override protected Builder self() { return this; }
Item3 - private 생성자나 열거 타입으로 싱글턴임을 보장해라
- 빌더 패턴이라고 사용했지만 오버라이드의 이점을 본것이 아닌지?
- 유일한 인스턴스를 반환하던 팩터리 메서드가 호출하는 스레드별로 다른 인스턴스를 넘겨주게 할 수 있다.
- 모든 인스턴스 필드를 transient라고 선언하고 readResolver 메서드를 제공해야 한다.
Item4 - 인스턴스화를 막으려거든 private 생성자를 사용해라
- private 생성자를 추가하면 클래스의 인스턴스화를 막을 수 있다.
Item5 - 자원을 직접 명시하지 말고 의존 객체를 주입을 사용해라
- 의존 객체 주입은 유연성과 테스트 용이성을 높혀준다.
Item6 - 불필요한 객체 생성을 피하라
- String.matches는 정규표현식으로 문자열 형태를 확인하는 가장 쉬운 방법이다. 성능이 중요한 상황에서 반복해 사용하기엔 적합하지 않다.