본문 바로가기
개발/JAVA

[effective java 3/E] 생성자 대신 정적 팩터리 메서드를 고려해보자

by 상용최 2020. 6. 21.
반응형

클래스는 생성자와 별도로 정적 팩터리 메소드를 제공할 수 있다. 

  • 정적 팩터리 메소드란 그 클래스의 인스턴스를 반환하는 단순한 정적 메서드를 일컫는다.

아래의 CustomBoolean Class 는 자바에 있는 Boolean 에서 설명에 필요한 부분만 발취해서 만든 간단한 클래스이다.

  • 아래의 기본 생성자 CustomBoolean 은 boolean 필드에 값을 세팅해서 새로운 인스턴스를 만들어준다.
  • 정적 메서드 valueOf는 기존에 만들어져있던 CustomBoolean 인스턴스를 반환해준다.
public class CustomBoolean {
    public static final CustomBoolean TRUE = new CustomBoolean(true);
    public static final CustomBoolean FALSE = new CustomBoolean(false);
    private final boolean value;

    public CustomBoolean(boolean value) {
        this.value = value;
    }

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

    public String toString() {
        return this.value ? "true" : "false";
    }
}
public final class main {

    public static void main(String[] args) {
        CustomBoolean trueBoolean = CustomBoolean.valueOf(true); // 정적 팩토리 메소드 사용
        CustomBoolean falseBoolean = new CustomBoolean(false);   // 생성자 사용

        System.out.println(trueBoolean.toString());
        System.out.println(falseBoolean.toString());
    }
}

 

사람도 그렇듯 정적 팩터리 메서드도 장점이 있지만 단점도 있다.

장점과 단점을 알아보도록 하겠다.

 

정적 팩터리 메서드의 장점

  • 이름을 가질 수 있다.
    생성자에 넘기는 매개변수와 생성자 자체만으로는 반환될 객체의 특성을 제대로 설명하지 못한다.
    반면 정적 팩터리는 이름만 잘 지으면 반환될 객체의 특성을 쉽게 묘사할 수 있다는 장점이있다.

    CustomBoolean Class를 아래와같이 수정해보겠다.
    main 메소드에서 CustomBoolean의 정적 메소드인  trueCustomBoolean 과 falseCustomBoolean 정적 메서드를 이용해서 인스턴스를 받고있다.
    기존에 생성자를 이용해서 값을 넘기면 매개변수를 이용해서 값을 유추해야하지만 
    정적 메소드를 이용한다면 메소드만 보고도 결과값이 이런거겠구나!! 하고 유추할 수 있게된다는 장점이있다.

 

public class CustomBoolean {
    public static final CustomBoolean TRUE = new CustomBoolean(true);
    public static final CustomBoolean FALSE = new CustomBoolean(false);
    private final boolean value;

    public CustomBoolean(boolean value) {
        this.value = value;
    }

    public static CustomBoolean trueCustomBoolean(){
        return TRUE;
    }

    public static CustomBoolean falseCustomBoolean(){
        return FALSE;
    }

    public String toString() {
        return this.value ? "true" : "false";
    }
}
public final class main {

    public static void main(String[] args) {
        CustomBoolean trueBoolean = CustomBoolean.trueCustomBoolean();
        CustomBoolean falseBoolean = CustomBoolean.falseCustomBoolean();

        System.out.println(trueBoolean.toString());
        System.out.println(falseBoolean.toString());
    }
}

 

  • 호출될때마다 새로운 인스턴스를 생성하지 않아도된다.
    Boolean 같은경우 True인지 False인지만 판단하면된다.
    판단할때마다 새로운 인스턴스를 생성한다면 낭비가 될 수 있다.
    이럴일은 없겠지만 극단적인 상황을 예로 들어보겠다.

    1000만개의 값을 판단할거고 거기에 각각 판단할 수 있는 필드를 둘것이다.
    이때 1000만개를 새로 만든다면 1000만의 공간을 필요로 할것이다.
    하지만 정적 메서드를 이용하여 기존에 만들어져있던 인스턴스를 반환한다면 단 2개 (TRUE, FALSE) 의 공간만을 필요로 하게된다.

    인스턴스를 통제하게 된다면 클래스를 싱글턴으로 만들수도, 인스턴스화 불가로 만들 수도 있게된다.

  • 반환 타입의 하위객체를 반환할 수 있는 능력이 있다.
  • 입력 매개변수에 따라 매번 다른 클래스의 객체를 반환할 수 있다.
    위의 두가지 특성은 하나의 예제로 알아보기로 한다.
    반환 타입의 하위 타입이기만 하면 어떤 클래스의 객체를 반환하든 상관없다.
    이것은 EnumSet 항목을 통해 알아보도록 하자.

    EnumSet 클래스의 noneOf 메소드를 보면 universe의 길이에 따라 RegularEnumSet과 JumboEnumSet을 선택해서 반환해주고 있다.

  • 정적 팩터리 메서드를 작성하는 시점에는 반환할 객체의 클래스가 존재하지 않아도 된다.
    이 특징은 서비스 제공자 프레임워크를 만드는 근간이 된다.
    대표적인 서비스 제공자 프레임워크의 예로를 JDBC가 있다.

    DriverManager.class 의 getConnection 정적 메서드는 반환타입이 Connection이다.
    그러나 Connection은 Interface이다.
    이로인해 구현체를 사용자가 원하는대로 정의하여 반환할 수 있다.

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

정적 팩터리 메서드의 단점

  • 상속을 하려면 pulbic이나 protected 생성자가 필요하니 정적 팩터리 메소드만 제공하면 하위 클래스를 만들 수 없다.
    이부분은 자바의 기본문법이니 따로 설명하지 않겠다.

  • 정적 팩터리 메서드는 문서가 없다면 프로그래머가 찾기 어렵다.
    정적 팩터리 메서드 방식 클래스를 인스턴스화할 방법을 알아내야한다.
    문서화를 통하여 사용하는법을 정리해 놓아야한다.

 

 

출처 : 이펙티브자바 3판 (effective java 3/E)

반응형

댓글