🏭 팩토리 패턴 (Factory Pattern)

2025. 9. 9. 15:59·Computer Science/Design Pattern

 

객체의 생성(create) 과정을 전담하는 클래스(공장)를 만들어, 객체 생성을 사용하는 코드로부터 분리/추상화하는 디자인 패턴입니다.

팩토리(Factory), 즉 '공장'이라는 이름처럼, 객체를 직접 new로 만드는 것이 아니라 '공장'에 요청하여 객체를 받아오는 방식입니다.

  • 핵심 정의: 객체를 사용하는 코드(클라이언트)에서 객체 생성 코드를 분리(추상화)하는 패턴입니다.
  • 패턴 방식: 상속 관계에 있는 두 클래스에서, 상위 클래스(추상 클래스)가 인터페이스와 같은 중요한 뼈대를 결정하고, 하위 클래스(구현 클래스)가 객체 생성에 관한 구체적인 내용을 결정합니다.

👍 팩토리 패턴의 장점

  • 느슨한 결합 (Loose Coupling): 객체를 사용하는 상위 클래스와 객체를 생성하는 하위 클래스가 분리됩니다. 이로 인해 상위 클래스는 어떤 구체적인 인스턴스가 생성되는지 전혀 알 필요 없이 약속된 '뼈대'(인터페이스)만 보고 작동하므로 유연성이 극대화됩니다.
  • 유지보수성 증가: 객체를 생성하는 모든 로직이 '공장(Factory)' 한곳에 중앙화되어 있습니다. 만약 객체 생성 방식(예: 생성자 변경)을 수정해야 할 때, 코드를 사용하는 모든 곳을 찾아다닐 필요 없이 딱 한 곳, 즉 해당 팩토리만 수정하면 되므로 유지보수성이 매우 높아집니다.

💻 코드 예시

1. 자바스크립트(JavaScript)의 팩토리 메서드 패턴

이 예시는 상위 CoffeeFactory를 상속받은 하위 팩토리(LatteFactory 등)가 구체적인 객체 생성을 담당하는 "팩토리 메서드" 패턴에 가깝습니다.

// 상위 클래스 (뼈대)
class CoffeeFactory {
  // static: CoffeeFactory.createCoffee()로 바로 호출 가능 (공장 가동)
  static createCoffee(type) {
    // 요청(type)에 맞는 구체적인 하위 공장(factory)을 찾음
    const factory = factoryList[type];
    // 해당 하위 공장에 실제 생산을 위임(delegate)
    return factory.createCoffee();
  }
}

// --- 실제 생산될 객체 (제품) ---
class Latte {
  constructor() {
    this.name = "latte";
  }
}

class Espresso {
  constructor() {
    this.name = "Espresso";
  }
}

// --- 하위 클래스 (구체적인 생산 공장) ---
class LatteFactory extends CoffeeFactory {
  static createCoffee() {
    return new Latte(); // 라떼 공장은 라떼만 생산
  }
}

class EspressoFactory extends CoffeeFactory {
  static createCoffee() {
    return new Espresso(); // 에스프레소 공장은 에스프레소만 생산
  }
}

// 공장 목록 (어떤 요청에 어떤 공장을 돌릴지)
const factoryList = { LatteFactory, EspressoFactory };

// --- 클라이언트 코드 (손님) ---
const main = () => {
  // 손님(main)은 그저 상위 공장(CoffeeFactory)에 요청할 뿐,
  // LatteFactory가 작동하는지, new Latte()가 호출되는지 모름.
  const coffee = CoffeeFactory.createCoffee("LatteFactory");
  console.log(coffee.name); // latte
};

main();

분석:

  • CoffeeFactory라는 상위 클래스(추상 공장)가 createCoffee라는 중요한 뼈대를 결정하고, 하위 클래스인 LatteFactory가 구체적인 new Latte() 생성을 결정합니다.
  • 이는 의존성 주입(DI)과는 약간 다릅니다. DI는 외부에서 생성된 객체를 주입(삽입)받는 것이고, 이 코드는 상위 팩토리가 하위 팩토리에게 생성을 위임(Delegate)하는 구조입니다. 둘 다 느슨한 결합을 추구한다는 공통점은 있습니다.
  • static 키워드 (정적 메서드): static으로 선언된 메서드는 클래스의 인스턴스(객체)가 아닌 클래스 자체에 속합니다. 따라서 new CoffeeFactory()처럼 객체를 만들지 않고도 CoffeeFactory.createCoffee()로 바로 호출할 수 있습니다. 프로그램 실행 시 메모리에 딱 한 번만 할당되므로, 유틸리티 함수나 팩토리 메서드처럼 객체의 상태와 관계없이 기능만 제공할 때 사용하기 좋습니다.

2. 자바(Java)의 팩토리 메서드 패턴

이 예시는 상속 대신, 하나의 중앙화된 팩토리 클래스가 switch 문을 통해 모든 객체 생성을 처리하는 "단순 팩토리(Simple Factory)" 패턴입니다.

// Enum: 커피 타입을 '상수 집합'으로 안전하게 관리
enum CoffeeType {
  LATTE,
  ESPRESSO
}

// Abstract Class (추상 클래스): 커피라는 제품의 기본 뼈대(설계도)
// new Coffee()는 불가능함.
abstract class Coffee {
  protected String name;

  public String getName() {
    return name;
  }
}

// --- 실제 제품 클래스 ---
class Latte extends Coffee {
  public Latte() {
    name = "latte"; // 설계도를 구체화
  }
}

class Espresso extends Coffee {
  public Espresso() {
    name = "Espresso"; // 설계도를 구체화
  }
}

// --- 중앙 객체 생성 공장 ---
class CoffeeFactory {
  // 이 공장은 요청(type)만 받으면 알아서 적절한 객체를 생산(switch)함
  public static Coffee createCoffee(CoffeeType type) {
    switch (type) {
      case LATTE:
        return new Latte();
      case ESPRESSO:
        return new Espresso();
      default:
        // 잘못된 요청이 들어오면 예외 발생
        throw new IllegalArgumentException("Invalid coffee type: " + type);
    }
  }
}

// --- 클라이언트 코드 (손님) ---
public class Main {
  public static void main(String[] args) {
    // 손님(Main)은 CoffeeFactory에 LATTE 타입만 요청함.
    // new Latte() 코드는 공장 내부에 숨겨져 있음(캡슐화).
    Coffee coffee = CoffeeFactory.createCoffee(CoffeeType.LATTE);
    System.out.println(coffee.getName()); // latte
  }
}

분석 및 용어 설명:

  • Enum (열거형 타입):
    • LATTE, ESPRESSO처럼 서로 연관된 상수의 집합을 정의할 때 사용하는 특별한 타입입니다.
    • 장점 1 (안정성): 문자열("Latte")이나 숫자(1) 대신 CoffeeType.LATTE라는 명확한 타입을 사용하므로, 컴파일 시점에 오류를 잡을 수 있고 코드 가독성이 올라갑니다.
    • 장점 2 (유지보수): 새로운 커피 타입(예: AMERICANO)을 추가할 때, 다른 파일을 건드릴 필요 없이 Enum 정의부와 팩토리의 switch문에 case만 추가하면 됩니다.
    • 장점 3 (스레드 세이프): Enum의 인스턴스는 JVM에 의해 단 하나만 생성되는 것이 보장됩니다. 이 특성 덕분에 Enum은 싱글톤 패턴을 구현하는 가장 간편하고 안전한(Thread-Safe) 방법 중 하나로 사용됩니다.
  • abstract class (추상 클래스):
    • '미완성 설계도'입니다. Coffee 클래스처럼, getName()같은 공통 기능은 구현해 두지만, 스스로는 new Coffee()를 통해 객체화될 수 없습니다. 반드시 Latte나 Espresso처럼 상속을 통해 세부 내용이 완성되어야만 하는 클래스를 의미합니다.

 

 


1. 팩토리 패턴에 대해 설명해주세요.

 

팩토리 패턴이란 클라이언트에서 객체 생성 코드를 분리하는 패턴입니다. 상속 관계에 있는 두 클래스에서 상위 클래스가 인터페이스와 같은 중요한 뼈대를 결정하고, 하위 클래스가 구체적인 내용을 결정합니다. 이를 통해 클라이언트 코드의 변경 없이 새로운 종류의 객체를 쉽게 추가할 수 있어, 시스템의 유연성과 확장성을 높이는 데 큰 장점이 있습니다.

'Computer Science > Design Pattern' 카테고리의 다른 글

⛓️ 프록시 패턴과 프록시 서버  (1) 2025.09.16
📡 옵저버 패턴 (Observer Pattern)  (0) 2025.09.09
⚔️ 전략 패턴 (Strategy Pattern)  (0) 2025.09.09
💡 싱글톤 패턴 (Singleton Pattern)  (0) 2025.09.09
👨‍💻 디자인 패턴과 주요 원칙  (0) 2025.09.09
'Computer Science/Design Pattern' 카테고리의 다른 글
  • 📡 옵저버 패턴 (Observer Pattern)
  • ⚔️ 전략 패턴 (Strategy Pattern)
  • 💡 싱글톤 패턴 (Singleton Pattern)
  • 👨‍💻 디자인 패턴과 주요 원칙
TECHNING
TECHNING
Hi! I'm techning
  • TECHNING
    TECHNING
    TECHNING
    • 분류 전체보기 (54)
      • Computer Science (45)
        • Design Pattern (11)
        • Programming Paradigm (4)
        • Network (15)
        • Operating System (6)
        • Database (6)
        • Data Structure (3)
      • Algorithm (5)
        • Python (3)
        • Java (1)
      • IT Insight (4)
  • hELLO· Designed By정상우.v4.10.4
TECHNING
🏭 팩토리 패턴 (Factory Pattern)
상단으로

티스토리툴바