본문 바로가기
Java/DesignPattern

팩토리 메서드 패턴 vs 추상 팩토리 패턴

by amungstudy 2025. 9. 7.

팩토리 메서드 패턴과 추상 팩토리 패턴은 객체 생성을 캡슐화 하는 패턴이며,

클라이언트와 구상 클래스가 서로 분리된 유연한 디자인을 구현할 수 있게 도와준다.

 

 

  • 팩토리 메서드: “어떤 구체 Product를 만들지”를 하위 Creator가 결정한다
  • 추상 팩토리: “어떤 제품군(여러 Product 계층) 을 만들지”를 팩토리 인스턴스 교체로 결정한다

언제 어떤 패턴을 쓰나?

  • 팩토리 메서드
    • 제품 계층만 다루고, 구체 타입 선택을 상속(하위 Creator) 으로 바꾸고 싶을 때.
    • 상위 로직(템플릿) 속에서 객체 생성 지점을 오버라이드로 바꾸고 싶을 때.
    • 클래스 수가 비교적 적고 “템플릿 메서드” 흐름이 중요할 때.
  • 추상 팩토리
    • 여러 제품 계층(예: Button/Checkbox/…)이 세트(제품군) 로 맞물려야 할 때.
    • 런타임에 환경별 세트 교체(Win ↔ Mac, Dev ↔ Prod)를 깔끔히 하고 싶을 때.
    • DI 컨테이너와 궁합이 좋음(팩토리 빈을 주입해 세트 스위칭).

장단점 요약

  • 팩토리 메서드
    • 장점: 상위 로직 재사용 + 하위에서 객체 선택 유연. 템플릿/훅 구조와 친함.
    • 단점: 제품군이 늘어나면 Creator/ConcreteCreator 조합이 많아질 수 있음.
  • 추상 팩토리
    • 장점: 제품군의 일관성 보장(혼종 방지), 세트 교체 용이.
    • 단점: 제품 계층·팩토리 인터페이스가 늘면서 구조가 커짐.

 

1) 팩토리 메서드 패턴 (Java 예제)

한 가지 Product 계층을 만들되, 어떤 구현체를 만들지는 하위 Creator가 결정.

 
// Product 계층
interface Transport {
    void deliver();
}

class Truck implements Transport {
    public void deliver() { System.out.println("Deliver by road in a box"); }
}

class Ship implements Transport {
    public void deliver() { System.out.println("Deliver by sea in a container"); }
}

// Creator 계층
abstract class Logistics {
    // 팩토리 메서드: 어떤 구체 Product를 만들지는 하위 클래스가 결정
    protected abstract Transport createTransport();

    // 비즈니스 로직(템플릿): 공통 흐름 안에서 Product 사용
    public void planDelivery() {
        Transport t = createTransport();
        System.out.println("Planning route...");
        t.deliver();
    }
}

class RoadLogistics extends Logistics {
    @Override protected Transport createTransport() { return new Truck(); }
}

class SeaLogistics extends Logistics {
    @Override protected Transport createTransport() { return new Ship(); }
}

// 사용
public class FactoryMethodDemo {
    public static void main(String[] args) {
        Logistics road = new RoadLogistics();
        road.planDelivery(); // -> Truck 생성

        Logistics sea = new SeaLogistics();
        sea.planDelivery();  // -> Ship 생성
    }
}

핵심 포인트

  • createTransport()가 “팩토리 메서드”.
  • 상위 Logistics는 공통 알고리즘(planDelivery)을 제공하고, 구체 객체 선택은 하위 클래스가 결정.

 

2) 추상 팩토리 패턴 (Java 예제)

버튼/체크박스처럼 여러 제품 계층이 있는 “제품군”을 OS별로 일관되게 생성.

 
// 제품 계층 1
interface Button {
    void render();
}

// 제품 계층 2
interface Checkbox {
    void check();
}

// 제품군 A (Windows)
class WinButton implements Button {
    public void render() { System.out.println("Render Windows Button"); }
}
class WinCheckbox implements Checkbox {
    public void check() { System.out.println("Check Windows Checkbox"); }
}

// 제품군 B (Mac)
class MacButton implements Button {
    public void render() { System.out.println("Render Mac Button"); }
}
class MacCheckbox implements Checkbox {
    public void check() { System.out.println("Check Mac Checkbox"); }
}

// 추상 팩토리: 제품군을 통째로 생성
interface GUIFactory {
    Button createButton();
    Checkbox createCheckbox();
}

// 구체 팩토리: 특정 제품군을 생성
class WinFactory implements GUIFactory {
    public Button createButton() { return new WinButton(); }
    public Checkbox createCheckbox() { return new WinCheckbox(); }
}
class MacFactory implements GUIFactory {
    public Button createButton() { return new MacButton(); }
    public Checkbox createCheckbox() { return new MacCheckbox(); }
}

// 클라이언트: 팩토리를 주입받아 일관된 제품군 사용
class Application {
    private final Button button;
    private final Checkbox checkbox;

    public Application(GUIFactory factory) {
        this.button = factory.createButton();
        this.checkbox = factory.createCheckbox();
    }

    public void drawUI() {
        button.render();
        checkbox.check();
    }
}

public class AbstractFactoryDemo {
    public static void main(String[] args) {
        GUIFactory factory = detectOSIsWindows() ? new WinFactory() : new MacFactory();
        Application app = new Application(factory);
        app.drawUI();
    }

    private static boolean detectOSIsWindows() {
        String os = System.getProperty("os.name", "").toLowerCase();
        return os.contains("win");
    }
}

핵심 포인트

  • GUIFactory가 “추상 팩토리”.
  • 클라이언트는 팩토리만 바꾸면 여러 제품 계층(Button, Checkbox)일관된 제품군으로 교체.

'Java > DesignPattern' 카테고리의 다른 글

Singleton Pattern 싱글턴 패턴  (0) 2025.09.07
템플릿 메소드 패턴  (0) 2024.06.03
팩토리 메서드 패턴  (0) 2024.05.16
MVVM 패턴  (0) 2023.07.27