JAVA

[Effective Java] Item 1. 생성자 대신 정적 팩터리 메서드를 고려하라

혀내 2023. 4. 30. 23:50
반응형

정적 팩토리 메소드를 사용할 때의 장점

1. 메소드가 이름을 가질 수 있다.

  • 즉, 메소드에서 반환될 객체의 특성을 잘 알 수 있다.
  • 한 클래스에 생성자가 여러 개 필요할 것 같다면 정적 팩터리 메서드로 바꾸고 각각의 차이를 잘 드러내는 이름을 지어주자.
class Menu {
    String name;
    String description;
    
    public static Menu createMenu(String name, String description) {
    	return new Menu(name, description);
    }
    
    public static Menu createMenuWithoutDescription(String name) {
    	return new Menu(name, "");
    }
    
    private Menu(String name, String description) {
    	this.name = name;
        this.description = description;
    }
}

 

 

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

  • 불변 클래스는 미리 만들어진 인스턴스나 새 인스턴스를 캐싱해 재활용할 수 있다.
  • 인스턴스를 통제해 싱글턴으로, 또는 인스턴스화 불가로 만들 수 있다.
public enum QuizAnswer {
    O,
    X;
}

public class Main {
    public static void main(String[] args) {
        // enum 클래스의 valueOf() 메소드도 정적 팩토리 메소드
        QuizAnswer oAnswer = QuizAnswer.valueOf("O");
        QuizAnswer oAnswer = QuizAnswer.valueOf("X");
	}
}

 

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

  • 반환할 객체의 클래스를 자유롭게 선택할 수 있다.

 

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

 

public class Blouse {

    public static Blouse of(int size) {
    	if (size < 90) {
            return new SmallBlouse();
        } else if (size < 100) {
            return new MediumBlouse();
        } else {
            return new LargeBlouse();
        }
    }
}

 

 

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

  • 서비스 제공자 프레임워크를 만드는 근간이 된다.
  • 예시) JDBC 프레임워크
    • 서비스 인터페이스 Connection : 구현체의 동작을 정의한다.
    • 제공자 등록 API DriverManager.registerDriver : 제공자가 구현체를 등록할 때 사용한다.
    • 서비스 접근 API DriverManager.getConnection : 클라이언트가 서비스 인스턴스를 얻을 때 사용한다.
    • 서비스 제공자 인터페이스 Driver(선택) : 서비스 인스턴스를 생성하는 팩터리 객체를 설명한다.
  • 서비스 제공자 프레임워크의 변형: Bridge Pattern, DI 프레임워크

 

 

정적 팩토리 메소드를 사용할 때의 단점

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

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

 

 

정적 팩터리 메서드의 명명 방식

from: 매개 변수를 하나 받아 해당 타입의 인스턴스를 반환하는 형변환 메서드이다.

Date d = Date.from(instant);

 

of: 여러 매개변수를 받아 적합한 타입의 인스턴스를 반환하는 집계 메서드이다.

Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);

 

valueOf: from과 of의 더 자세한 버전이다.

BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);

 

instance / getInstance: 매개변수로 명시한 인스턴스를 반환하나 같은 인스턴스임을 보장하지 않는다.

StackWalker luke = StackWalker.getInstance(options);

 

create / newInstance: instance와 같지만 매번 새로운 인스턴스를 생성해 반환함을 보장한다.

Object newArray = Array.newInstance(classObject, arrayLen);

 

getType: getInstance와 같으나 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용한다.

  • Type: 팩터리 메서드가 반환할 객체 타입
FileStore fs = Files.getFileStore(path);

 

newType: newInstance와 같으나 생성할 클래스가 아닌 다른 클래스에 팩터리 메서드를 정의할 때 사용한다.

BufferedReader br = Files.newBufferedReader(path);

 

type: getType과 newType의 간결한 버전이다.

List<Complaint> litany = Collections.list(legacyLitany);

 

 

 

 

 

 

 

 

이펙티브 자바 Effective Java 3/E - YES24

자바 플랫폼 모범 사례 완벽 가이드 - Java 7, 8, 9 대응자바 6 출시 직후 출간된 『이펙티브 자바 2판』 이후로 자바는 커다란 변화를 겪었다. 그래서 졸트상에 빛나는 이 책도 자바 언어와 라이브

www.yes24.com

 

반응형