티스토리 뷰

donaricano-btn
반응형

보통 클래스의 인스턴스를 생성할 때 new 키워드를 통해 생성자를 사용하는 방법입니다. 하지만 생성자를 사용하는 방법은 때로는 조금 귀찮을 수 있습니다. 생성자 아규먼트의 순서를 헷갈린다거나 때로는 아규먼트가 너무나 많아서 그냥 코드 자체가 지저분해 지는 것이 싫을 수도 있겠죠. 이럴 때 사용할 수 있는 것이 정적 팩더리 메서드(static factory method)를 사용하는 것입니다.

 

public static final <T> List<T> emptyList() {
    return (List<T>) EMPTY_LIST;
}

 

위 코드는 실제 Collections 클래스에 포함되어 있는 텅 빈 리스트를 반환하는 정적 팩터리 메서드 입니다. 이런 방법에는 장점과 단점이 모두 존재합니다. 장점을 먼저 알아보겠습니다.

 

1. 이름을 가질 수 있다.

위 코드에서 정적 팩토리 메서드는 emptyList 라는 이름을 가지고 있습니다. 코드를 읽는 사람들은 이 메서드의 이름을 통해서 어떤 객체를 반환 받는 것인지 쉽게 이해할 수 있습니다. 아무리 단순한 정적 팩토리 메서드라고 하더라도 생성자를 사용하는 것에 비해 어떤 역할을 하는 것인지 훨씬 명확하게 알 수 있습니다.

 

한 클래스에 여러 생성자가 필요할 것 같다면, 생성자를 정적 팩터리 메서드로 바꾸고 각각의 차이를 잘 드러내는 이름을 지어주는 것이 좋습니다.

 

2. 호출될 때마다 인스턴스를 새로 생성하지 않아도 된다.

호출 될 때 마다 매번 인스턴스를 새로 생성한다면 메모리 영역에 낭비하는 공간이 많이 생길 수 밖에 없습니다. 때로는 매번 새롭게 인스턴스를 생성하지 않아도 될 때가 있죠. 그럴 때 정적 팩터리 메서드는 좋은 해답이 됩니다. 매번 new 키워드를 사용할 필요가 없으니까요.

 

3. 반환 타입의 하위 타입 객체를 반환할 수 있는 능력이 있다.

class PineapplePizza extends Pizza {
    // ...
}

class PeperoniPizza extends Pizza {
    // ...
}

class Pizza {

    public static Pizza of(String ingredient) {
        if ("pineapple".equals(ingredient)) {
            return new PineapplePizza();
        }
        return new PeperoniPizza();
    }
    
    // ...

}

 

위 코드에서 처럼 상속관계에 있는 하위 클래스를 얼마든지 반환할 수 있습니다. 이를 통해 코드를 훨씬 더 유연하게 만들 수 있습니다. 이 인스턴스를 사용하는 클라이언트는 내부에서 어떤 인스턴스가 반환되는지 알 필요가 없겠죠.

 

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

class Pizza {

    public static Pizza of(Pineapple pineapple) {
        return new PineapplePizza();
    }

    public static Pizza of(Peperoni peperoni) {
        return new PeperoniPizza();
    }
    
    // ...
    
}

 

위 코드에서 처럼 매개변수에 따라 각각 다른 하위 클래스를 반환하게 만들 수도 있다. 역시 코드를 훨씬 더 유연하게 만들어주게 됩니다. 마찬가지로 클라이언트는 내부에서 어떤 인스턴스가 반환됐는지 알지 못합니다.

 

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

class Pizza {

    public static Pizza getNewInstance() {
        PineapplePizza pineapplePizza = null;
        try {
            // 컴파일 시간에 알려지지 않은 클래스 객체를 생성
            Class<?> childClass = Class.forName("com.tistory.webfirewood.effectivejava.PineapplePizza");
            pineapplePizza = (PineapplePizza) childClass.newInstance();
        } catch (ClassNotFoundException e) {
            // ...
        } catch (InstantiationException  e) {
            // ...
        } catch (IllegalAccessException  e) {
            // ...
        }
        return pineapplePizza;
    }
    
    // ...
    
}

 

때로는 컴파일 시점에 알려지지 않은 클래스 객체를 생성하게 될 때도 있습니다. 이런경우 정적 팩터리 메서드를 사용하면 쉽게 구현할 수 있습니다.

 

이렇듯 정적 팩터리 메서드는 다양한 장점을 가지고 있지만 단점도 존재합니다. 대표적인 것이 다음 두가지 입니다.

 

1. 상속을 하려면 생성자가 필요한데 정적 팩터리 메서드만 제공하면 하위 클래스를 만들 수 없다.

말 그대로 상속을 하려면 public 이나 protected 생성자가 필요한데 이런 생성자 없이 정적 팩터리 메소드만 제공하면 상속이 되지 않는다는 의미 입니다.

 

2. 정적 팩터리 메서드는 프로그래머가 찾기 어렵다.

생성자 처럼 모든 클래스에 공통적으로 구현되는 부분이 아니다 보니 사용하는 개발자 입장에서는 어떤 메서드를 사용해야할지 직접 알아봐야 합니다. 아주 많은 정적 팩토리 메소드가 제공된다면 개발자는 그 메소드를 다 읽어봐야 할테니 시간이 걸리게 될 것입니다.

반응형
donaricano-btn
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함