자바 디자인 패턴 용어 사전
생성 패턴Factory Method

팩토리 메서드

객체 생성을 하위 클래스에 위임하는 패턴. 추상 팩토리는 관련 제품 '군'을 통째로 만든다.

객체를 무엇으로 만들지의 결정을 미루는 패턴들.

팩토리 메서드 — 생성을 하위 클래스로

abstract class Dialog {
    abstract Button createButton();          // 팩토리 메서드

    void render() {
        Button b = createButton();           // 무엇이 만들어질지 여기서는 모른다
        b.onClick(this::close);
    }
}

class WindowsDialog extends Dialog {
    Button createButton() { return new WindowsButton(); }
}

"뼈대는 상위가 정하고 부품은 하위가 정한다" — Template Method와 짝을 이룬다.

추상 팩토리 — 제품 '군'을 통째로

interface UIFactory {
    Button createButton();
    Checkbox createCheckbox();          // 여러 종류를 한 팩토리가 만든다
}

class MacFactory implements UIFactory {
    public Button createButton() { return new MacButton(); }
    public Checkbox createCheckbox() { return new MacCheckbox(); }
}

목적: 함께 쓰여야 하는 것들이 섞이지 않게 한다

  • MacButton 과 WindowsCheckbox 가 섞이는 일을 구조적으로 막는다

둘의 차이

팩토리 메서드제품 '하나'.상속으로 확장한다
추상 팩토리제품 '군'.합성(팩토리 객체를 주입)으로 쓴다
  • 추상 팩토리는 내부적으로 팩토리 메서드를 여러 개 갖는 형태가 흔하다

정적 팩토리 메서드는 다른 것이다

// GoF 패턴이 아니라 '관용구' 다
Integer.valueOf(1)
List.of(1, 2, 3)
Optional.ofNullable(x)

장점

  • 이름을 줄 수 있다 (생성자는 클래스명으로 고정)
  • 매번 새 객체를 안 만들어도 된다 (캐싱)
  • 하위 타입을 반환할 수 있다

면접에서 "팩토리 패턴"이라고 하면 셋 중 무엇인지 되묻는 게 안전하다.

언제 과한가

구현이 하나뿐이고 늘어날 계획도 없다면 그냥 new 가 낫다

  • 팩토리는 '무엇을 만들지가 런타임에 갈릴 때' 값을 한다

면접 함정

  • "팩토리 메서드는 static이다" → GoF의 팩토리 메서드는 상속으로 재정의하는 인스턴스 메서드다.
  • "추상 팩토리가 더 발전된 형태" → 목적이 다르다. 제품이 하나면 팩토리 메서드가 맞다.

실무에서 가장 흔한 형태

// 타입 → 구현 매핑을 한곳에 모은다
@Component
class PayMethodFactory {
    private final Map<PayType, PayMethod> methods;

    PayMethodFactory(List<PayMethod> list) {          // DI 가 구현을 전부 주입한다
        this.methods = list.stream().collect(toMap(PayMethod::type, identity()));
    }

    PayMethod get(PayType type) {
        return Optional.ofNullable(methods.get(type))
            .orElseThrow(() -> new IllegalArgumentException("지원하지 않는 결제: " + type));
    }
}

새 결제 수단을 추가할 때 이 팩토리를 안 고쳐도 된다 — 구현체를 빈으로 등록하기만 하면 목록에 자동으로 들어온다. OCP가 프레임워크 수준에서 완성된 형태다.

이름 짓기

  • of · from · valueOf — 변환·생성 (List.of · Integer.valueOf)

  • getInstance — 캐싱된 인스턴스

  • newInstance — 항상 새 인스턴스

  • create — 일반적인 생성

  • 이름만으로 "매번 새로 만드는가" 를 알 수 있게 하는 것이 관례다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 생성 패턴 — 객체를 만드는 일을 떼어낸다