[아이템 1] 생성자 대신 정적 팩토리 메소드를 고려하라

ajufresh·2020년 2월 18일
0

Effective Java 3/E

목록 보기
1/9
post-thumbnail

블로그에 게시하는 위 글은 전체적인 내용 정리가 아닌
책을 읽으면서 새로 알게된 내용이나 제가 중요하다고 생각하는 내용을 정리한 글입니다.

백기선님의 유튜브와 책을 병행했다.

정적 팩토리 메소드(static)의 장점

이름을 가질 수 있다.

생성자에 비해 이름을 명시적으로 지을 수 있고, 생성자는 시그니처가 제약적이지만 정적 메소드는 자유롭다.

class A {
	
    private String chip;
    private String dale;
    
    // 불가능
    public A(String chip){
    	this.chip = chip;
    }
    
    public A(String dale){ 
    	this.dale = dale;
    }
    
    // 가능
    public static A getChip(String chip)  {
    	A a = new A();
        a.chip = chip;
        
        return a;
    }
    
    public static A getDale(String dale)  {
    	A a = new A();
        a.dale = dale;
        
        return a;
    }
    
    
}

꼭 객체를 새로 만들 필요가 없다.

생성자는 반드시 객체를 리턴해야하지만, 정적 메소드는 그렇지 않다.
(캐싱을 할 수도 있고, 상수를 반환할 수도 있고, 미리 만들어둔 객체를 반환할 수도 있다.)

class A {
	
    private static final String chip = "chip";
    
    // 가능
    public static A getChip(String chip)  {
    	
        return chip;
    }
    
}

하위 타입 객체를 반환할 수 있다.

생성자는 리턴값이 없지만, 정적 팩토리 메소드는 반환값을 유연하게 사용할 수 있다.
그 중, 반환값을 하위 타입의 객체로도 반환을 할 수 있다.
코드를 보면 이해가 간다.

class A {

    public static B checkInput(String discountCode)  {
    	return new B();    
    }
}

class B extends A { }

이런식으로 사용이 가능하다.

매개변수에 따라 다른 클래스 객체를 반환할 수 있다.

대표적인 예로 EnumSet이 있다.

    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else
            return new JumboEnumSet<>(elementType, universe);
    }

실제 EnumSet의 코드이다. RegularEnumSet, JumboEnumSet 모두 EnumSet을 상속받고 있다.
noneOf()는 universe의 length를 비교해서 서로 다른 클래스 타입을 반환하고 있다.

메서드를 작성하는 시점에는 반환객체의 클래스가 없어도 된다

정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.

세 번은 읽어봤는데 도통 무슨 소리인지 모르겠다 ...
나중에 이해하게 되면 추가 예정

정적 팩토리 메소드(static)의 단점

상속을 위해서는 생성자가 필수다.

제목 그대로이다.
정적 팩토리 메소드만 가지고는 상속이 불가능하다.
public또는 protected 생성자가 반드시 필요하다.

메소드를 프로그래머가 찾기 어렵다.

API에서 처리해주지 않는다.

대신 정적 메소드에서 흔하게 사용하는 명명 방식들이 있다.

  • from : 매개변수를 받아 해당 타입의 인스턴스를 반환 (형 변환)
  • of : 여러 매개변수를 받아 적합한 타입의 인스턴스 반환 (집계)
  • valueOf : from과 of의 더 자세한 버전
  • instance, getInstance : 매개변수로 명시한 인스턴스 반환 (같은 인스턴스 보장X)
  • create, newInstance : 매개변수로 명시한 인스턴스 반환 (생성)
  • getType : getInstance와 같지만 다른 클래스에 팩터리 메소드를 정의할 때 사용
  • newType : newInstance와 같지만 다른 클래스에 팩터리 메소드를 정의할 때 사용
  • type : getType, newType의 축약형
profile
공블로그

0개의 댓글