책/EffectiveJava

1장 객체의 생성과 파괴

kkkkkdddddhhhhh 2024. 8. 24. 19:40

정적 팩토리 메서드를 고려하라 

public class Boolean {
    public static final Boolean TRUE = new Boolean(true);
    public static final Boolean FALSE = new Boolean(false);

    private final boolean value;

    private Boolean(boolean value) {
        this.value = value;
    }

    public static Boolean valueOf(boolean b) {
        return (b ? TRUE : FALSE);
    }
}

 

정팩 팩토리 메서드가 생성자보다 좋은 이유 다섯가지

  1. 이름을 가질 수 있다.
    1. 이름을 잘 지으면 객체의 특성을 쉽게 묘사할 수 있다.
    2. 한 클래스에 시그니처가 여러개인 생성자가 존재할 경우 정적 패토리 메서드를 사용해 각각의 차이를 잘 드러내는 이름을 짓자.
  2. Private 접근제어를 가진 내부 생성자를 이용하기 때문에 
    1. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.
      1. 인스턴스의 생명주기를  클래스내에서 제어 가능하다 -> 이를 인스턴스 통제라함
      2. 객체를 싱글톤으로 만들수도, 인스턴화가 불가능한 객체로 만들 수 도있다.
    2. 캐싱이 가능하다 
      1. 외부 생성자가 아닌 Private접근자인 내부 생성자를 이용해 생성하기 때문에 
      2. 때문에 생성 비용이 큰 객체를 자주 요청하는 상황일 경우 용이하다.
  3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.
    1. 정적 팩토리 메서드의 반환타입을 추상클래스 혹은 인터페이스로 설정한 뒤 그 하위 클래스인 구현체를 반환가능하다.
    2. 반환 타입을 추상화함으로서 객체는 유연성을 가진다. 
    3. 클래스 내부 로직을 숨길 수 있어 캡슐화의 이점 또한 존재한다.
    4. 가장 큰 장점은 아무래도 "추상화" 해당 객체를 사용할때 코드 작성자는 해당 객체의 내부 로직과 반환 타입에 대해 정확히 파악하지 않아도 객체의 역할과 책임을 쉽게 이해하고 사용 가능하다.
  4. 입력 매개변수에 따라 배번 다르클래스의 객체르 반환할 수 있다.
    1. 3번의 장점과 비슷한 이유 
  5. 정적 팩토리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다. 
    1. 정적 팩토리 메서드는 추상화된 타입을 반환하기에 작성당시에 구현체가 존재하지 않아도된다. 구현체는 나중에 개발되거나 런타임 환경에서 동적으로 구현되어도 괜찮다는 뜻 이것도 3번째 장점과 비슷한듯

 

단점에대해서도 알아보자

  1. 상속을 하려면 publicdlsk protected 생성자가 필요하다. 
    1. 하지만 이러한 단점은 상속보단 컴포지션을 사용하라는 점을 지켜야되는 제약으로 오히려 장점이 될 수 도...
  2. 정적 팩토리 메서드는 프로그래머가 찾기 어렵다.
    1. API 설명란에 생성자처럼 명확하게 드러나지않아 정적 팩토리 메서드로 인스턴스화된 객체의 내부 로직 파악이 힘들 수 있다.

 

  • from:
    • 하나의 매개변수를 받아 해당 타입의 인스턴스를 반환하는 형변환 메서드
    • 예: Date.from(instant)
  • of:
    • 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드
    • 예: EnumSet.of(JACK, QUEEN, KING)
  • valueOf:
    • from과 of의 더 자세한 버전
    • 예: BigInteger.valueOf(Integer.MAX_VALUE)
  • instance 혹은 getInstance:
    • (매개변수를 받는다면) 매개변수로 명시한 인스턴스를 반환하지만, 같은 인스턴스임을 보장하지는 않음
    • 예: StackWalker.getInstance(options)
  • create 혹은 newInstance:
    • instance 혹은 getInstance와 같지만, 매번 새로운 인스턴스를 생성해 반환함을 보장
    • 예: Array.newInstance(classObject, arrayLen)
  • getType:
    • getInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩토리 메서드를 정의할 때 사용
    • 예: Files.getFileStore(path)
  • newType:
    • newInstance와 같으나, 생성할 클래스가 아닌 다른 클래스에 팩토리 메서드를 정의할 때 사용
    • 예: Files.newBufferedReader(path)
  • type:
    • getType과 newType의 간결한 버전
    • 예: Collections.list(legacyLitany)

핵심 정리 -> 정적 팩토리 메서드와 public 생성자 각각의 쓰임새가 존재한다. 다만 정적 팩토리 메서드를 이용하는 경우가 더 이로운 상황이 많기때문에 정적 팩토리 메서드로 코드를 먼저 작성해보는 습관을 가져보자.

 

생성자에 매개변수가 많다면 빌더를 고려하라 

정적 팩토리 메서드와 public 생성자에겐 같은 단점이 존재한다.

->선택적 매개변수가 많을 경우 적절한 대응이 어렵다.

 

매개변수가 많아질 경우 코드를 작성하거나 읽기도 어려워진다. 

또한 매개변수의 순서가 잘못될 경우 컴파일 과정에서는 문제가 발생하지 않아도 런타임 상황에서 예외가 발생 할 수 있다.

 

빌더패턴 : 점층적 생성자 패턴과 자바빈즈 패턴의 장점을 취한 디자인 패턴

선택적 매개변수를 먼저 초기화 후 

내부 스태틱 클래스인 빌더 클래스에서 매개변수를 받고 초기화 한다.

 

 

' > EffectiveJava' 카테고리의 다른 글

10장 예외  (0) 2024.09.05
4장 클래스와 인터페이스  (1) 2024.08.31