추상 팩토리 패턴

상세 제품을 하나하나 지정하지 않아도 부모 클래스에서 관련 객체들의 패밀리(제품군)를 생성할 수 있게 하는 패턴 

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

  팩토리 메서드 추상 팩토리 메서드
생성 대상 단일 제품 제품군(패밀리)
예시 Transport 하나 생성 Chair + Sofa + Table 세트 생성
목적 어떤 제품을 만들지 어떤 스타일의 제품군을 만들지

 

연습 문제

아래 코드를 추상 팩토리 패턴으로 리팩토링 해보세요.

public class Main {
    public static void main(String[] args) {
        String type = "modern";

        orderChair(type);
        orderSofa(type);
        orderTable(type);
    }

    public static void orderChair(String style) {
        if (style.equals("modern")) {
            new ModernChair().sitOn();
        } else if (style.equals("victorian")) {
            new VictorianChair().sitOn();
        } else if (style.equals("artdeco")) {
            new ArtDecoChair().sitOn();
        }
    }

    public static void orderSofa(String style) {
        if (style.equals("modern")) {
            new ModernSofa().lieOn();
        } else if (style.equals("victorian")) {
            new VictorianSofa().lieOn();
        } else if (style.equals("artdeco")) {
            new ArtDecoSofa().lieOn();
        }
    }

    public static void orderTable(String style) {
        if (style.equals("modern")) {
            new ModernTable().putCoffee();
        } else if (style.equals("victorian")) {
            new VictorianTable().putCoffee();
        } else if (style.equals("artdeco")) {
            new ArtDecoTable().putCoffee();
        }
    }
}

public class ModernChair {
    public void sitOn() {
        System.out.println("현대식 의자에 앉습니다. 🪑");
    }
}

public class ModernSofa {
    public void lieOn() {
        System.out.println("현대식 소파에 눕습니다. 🛋️");
    }
}

public class ModernTable {
    public void putCoffee() {
        System.out.println("현대식 테이블에 커피를 놓습니다. ☕");
    }
}

// VictorianChair, VictorianSofa, VictorianTable...
// ArtDecoChair, ArtDecoSofa, ArtDecoTable...

 

현재 문제점

  1. 스타일 추가 시 모든 메서드 수정 필요 - 새 스타일 추가하면 orderChair, orderSofa, orderTable 전부 수정
  2. 스타일 불일치 가능 - 실수로 orderChair("modern") + orderSofa("victorian") 조합 가능
  3. 중복 코드 - 각 메서드마다 동일한 if-else 구조 반복

 

요구사항

  • 하나의 팩토리에서 생성된 제품들은 항상 같은 스타일임이 보장되어야 합니다.

  • AbstractFactory = FurnitureFactory 인터페이스
  • ConcreteFactory = ModernFurnitureFactory, VictorianFurnitureFactory, ArtDecoFurnitureFactory
  • AbstractProduct = Chair, Sofa, Table 인터페이스
  • ConcreteProduct = ModernChair, VictorianChair, ArtDecoChair 등

 

정답

제품들은 종류(의자, 소파, 테이블)와 스타일(Modern, Victorian, ArtDeco) 두 가지 축으로 분류됩니다.

종류 → 인터페이스로 추상화 (Chair, Sofa, Table) 스타일 → 팩토리 클래스로 묶음 (ModernFurnitureFactory가 Modern 스타일 제품군 전체 생성)

이렇게 하면 하나의 팩토리에서 생성된 제품들은 항상 같은 스타일임이 보장됩니다.

 

1. 제품 인터페이스 정의

public interface Chair {
    void sitOn();
}

public interface Sofa {
    void lieOn();
}

public interface Table {
    void putCoffee();
}

2. 구체 제품 클래스 (인터페이스 구현)

public class ModernChair implements Chair {
    public void sitOn() {
        System.out.println("현대식 의자에 앉습니다. 🪑");
    }
}

public class ModernSofa implements Sofa {
    public void lieOn() {
        System.out.println("현대식 소파에 눕습니다. 🛋️");
    }
}

public class ModernTable implements Table {
    public void putCoffee() {
        System.out.println("현대식 테이블에 커피를 놓습니다. ☕");
    }
}

// Victorian, ArtDeco도 동일하게 각 인터페이스 구현

3. 추상 팩토리 인터페이스

public interface FurnitureFactory {
    Chair createChair();
    Sofa createSofa();
    Table createTable();
}

4. 구체 팩토리 클래스

public class ModernFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new ModernChair();
    }

    @Override
    public Sofa createSofa() {
        return new ModernSofa();
    }

    @Override
    public Table createTable() {
        return new ModernTable();
    }
}

public class VictorianFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new VictorianChair();
    }

    @Override
    public Sofa createSofa() {
        return new VictorianSofa();
    }

    @Override
    public Table createTable() {
        return new VictorianTable();
    }
}

public class ArtDecoFurnitureFactory implements FurnitureFactory {
    @Override
    public Chair createChair() {
        return new ArtDecoChair();
    }

    @Override
    public Sofa createSofa() {
        return new ArtDecoSofa();
    }

    @Override
    public Table createTable() {
        return new ArtDecoTable();
    }
}

5. 클라이언트 코드

public class Main {
    public static void main(String[] args) {
        String type = "modern";

        FurnitureFactory factory;
        if (type.equals("modern")) {
            factory = new ModernFurnitureFactory();
        } else if (type.equals("victorian")) {
            factory = new VictorianFurnitureFactory();
        } else {
            factory = new ArtDecoFurnitureFactory();
        }

        // 팩토리에서 생성된 제품들은 항상 같은 스타일!
        Chair chair = factory.createChair();
        Sofa sofa = factory.createSofa();
        Table table = factory.createTable();

        chair.sitOn();
        sofa.lieOn();
        table.putCoffee();
    }
}

 

+ Recent posts