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

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


아이템 1: 생성자 대신 정적 팩터리 메서드를 고려하라

📌 정적 팩터리 메서드란?

  • 클래스에서 객체를 생성할 때 보통은 new를 이용하여 생성자를 호출합니다.

  • 정적 팩터리 메서드는 생성자 대신 **정적인 메서드(static method)**를 통해 객체를 만들어 반환합니다.

간단한 비교 예시

// 전통적인 생성자 방식
Person person = new Person("John", 25);

// 정적 팩터리 메서드 방식
Person person = Person.fromNameAndAge("John", 25);

📌 정적 팩터리 메서드의 장점

1️⃣ 이름을 가질 수 있다 (명확한 의도 전달)

  • 생성자는 클래스 이름과 같아서, 어떤 의도로 객체를 만드는지 불명확할 때가 있습니다.

  • 팩터리 메서드는 이름으로 객체 생성의 의미를 명확히 할 수 있습니다.

예시

LocalDate date = LocalDate.of(2025, 3, 7); // 명확한 의도를 전달하는 메서드명

2️⃣ 객체 재사용이 가능하다 (성능 개선)

  • 매번 새로운 객체를 만들 필요가 없어서 성능을 개선할 수 있습니다.

  • 이미 만들어진 객체를 재사용(캐싱)할 수 있습니다.

  • 대표적인 예: 자바의 Boolean.valueOf(true) 메서드

예시 코드

public class Person {
    private static final Person COLT = new Person("Colt", 28);

    private String name;
    private int age;

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static Person getColt() {
        return COLT; // 항상 같은 인스턴스를 반환 (재사용)
    }
}

// 사용 예시
Person colt1 = Person.getColt();
Person colt2 = Person.getColt();
// colt1과 colt2는 같은 객체이다. (메모리 절약)

3️⃣ 하위 타입 객체를 반환할 수 있다 (유연성)

  • 팩터리 메서드는 자신이 선언한 반환 타입의 하위 타입 객체를 반환할 수 있습니다.

  • 인터페이스의 구현체를 외부에 노출시키지 않고, 상황에 따라 다른 객체를 반환할 수 있습니다.

예시 (Java의 EnumSet)

EnumSet<Color> colors = EnumSet.noneOf(Color.class);
// EnumSet 내부에서 상황에 맞는 RegularEnumSet 혹은 JumboEnumSet을 반환 (사용자는 내부 클래스를 몰라도 됨)

4️⃣ 상황에 따라 다양한 클래스의 객체 반환 가능

  • 입력 매개변수에 따라 각기 다른 객체를 반환하는 로직을 담을 수 있습니다.

  • 반환할 객체의 클래스는 호출 당시 상황에 따라 동적으로 결정됩니다.

예시 코드

public static Animal createAnimal(String type) {
    if ("cat".equals(type)) {
        return new Cat();
    } else if ("dog".equals(type)) {
        return new Dog();
    }
    return null;
}

// 사용 예시
Animal pet = AnimalFactory.createAnimal("cat");

5️⃣ 객체를 생성할 클래스가 꼭 미리 존재할 필요가 없다

  • 서비스 제공자 프레임워크(예: JDBC)는 정적 팩터리를 활용하여, 실제 사용할 클래스를 나중에 정할 수 있도록 유연성을 제공합니다.

  • 이는 프레임워크가 다양한 구현체들을 쉽게 관리할 수 있도록 돕습니다.

대표적 예시 (JDBC)

  • DriverManager.getConnection()은 데이터베이스의 종류에 따라 다른 커넥션 객체를 반환할 수 있습니다.


📌 정적 팩터리 메서드의 단점 (주의할 점)

  • 상속을 어렵게 만듦 정적 팩터리 메서드를 사용하려면 생성자가 private로 설정되기 때문에, 클래스를 상속하기 어려워집니다.

  • 찾기 어려울 수 있음 생성자처럼 명확히 드러나지 않아 API 문서를 잘 확인해야 합니다. 이 점은 흔히 쓰는 네이밍 패턴(from, of, valueOf, getInstance, newInstance)으로 완화할 수 있습니다.


📌 정적 팩터리 메서드의 대표적인 네이밍 관례

메서드 이름
설명
예시

from

하나의 매개변수를 받아 인스턴스를 반환

Date date = Date.from(instant);

of

여러 매개변수를 받아 인스턴스를 반환

List<String> list = List.of("A","B");

valueOf

기본형 등을 받아 적절한 인스턴스를 반환

Integer i = Integer.valueOf("123");

getInstance

동일한 인스턴스 반환을 보장하지 않음

Calendar cal = Calendar.getInstance();

create

항상 새로운 인스턴스 반환을 보장

Array array = Array.create(5);

newInstance

항상 새로운 인스턴스 생성

Object obj = Class.newInstance();


✅ Nutshell (한눈에 보는 요약)

정적 팩터리 메서드란?

  • 생성자 대신 이름을 가진 정적 메서드를 통해 객체를 생성하는 방식입니다.

장점

  • ✅ 메서드 이름을 통해 명확하게 의도 전달 가능

  • ✅ 객체 재사용을 통해 성능 개선 가능

  • ✅ 하위 타입이나 다양한 클래스 객체를 반환 가능 (유연성)

  • ✅ 서비스 프레임워크 제작 시 유리

단점

  • ⚠️ 상속을 어렵게 할 수 있음

  • ⚠️ 생성자보다 발견하기 어려울 수 있음

📖 한 줄 결론: 정적 팩터리 메서드는 이름과 재사용성을 통해 객체 생성의 명확성, 성능, 유연성을 높이지만, 상속 시에는 신중히 고려해야 합니다.


Last updated