[Design Pattern] 팩토리 메소드 패턴(Factory Method Pattern)

in·2023년 10월 12일
0

Design Pattern

목록 보기
5/8

📌 팩토리 메소드 패턴(Factory Method Pattern)

객체를 생성하기 위해 인터페이스를 정의하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스가 내리도록 하는 패턴
➡️ 하위 클래스에서 팩토리 메소드를 오버라이딩해서 객체를 반환하는 패턴

사용 상황

  • 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때
  • 생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때
  • 객체 생성의 책임을 몇 개의 보조 서브 클래스 가운데 하나에게 위임하고, 어떤 서브 클래스가 위임자인지에 대한 정보를 국소화시키고 싶을 때

구조 & 참여자

Product

  • 팩토리 메소드가 생성하는 객체의 인터페이스 정의

ConcreteProduct

  • Product 클래스에 정의된 인터페이스를 실제로 구현하는 클래스

Creator

  • Product 타입의 객체를 반환하는 팩토리 메소드를 선언하는 클래스
  • 팩토리 메소드를 기본적으로 구현, ConcreteProduct 객체를 반환
  • Product 객체의 생성을 위해 팩토리 메소드 호출

ConcreteCreator

  • 팩토리 메소드를 재정의하여 ConcreteProduct의 인스턴스 반환

구현 시 고려사항

팩토리 메소드 패턴의 구현 방법은 2가지가 있다.

  • Creator를 추상 클래스로 정의하고 팩토리 메소드는 abstract로 선언하는 방법
  • Creator가 구체 클래스이고, 팩토리 메소드의 기본 구현을 제공하는 방법

팩토리 메소드의 인자를 통해 다양한 Product를 생성하게 한다.

  • 팩토리 메소드에 잘못된 인자가 들어올 경우 런타임 에러 처리에 대해 고민할 것
  • Enum 등을 사용하는 것도 고려할 필요가 있다.

장점

  • 팩토리 메소드 패턴은 응용프로그램에 국한된 클래스가 코드에 종속되지 않게 해준다.
  • 응용프로그램은 Product 클래스에 정의된 인터페이스만 동작하도록 코드가 만들어지기 때문에 사용자가 정의한 어떤 ConcreteProduct 클래스가 와도 동작할 수 있다.
  • SRP
  • OCP

단점

  • 패턴 구현에 의한 코드가 복잡해질 수 있다.

예제1

// Product
interface Pizza {
    void prepare();
    void bake();
    void box();
}

// ConcreteProduct
class NYStyleCheesePizza implements Pizza { ... }

class NYStylePepperoniPizza implements Pizza { ... }
// Creator
abstract class PizzaStore {
    public Pizza orderPizza(String type) {
        Pizza pizza = createPizza(type);    // factory method
        pizza.prepare();
        pizza.bake();
        pizza.box();
        return pizza;
    }

    // factory method
    abstract Pizza createPizza(String type);
}
// ConcreteCreator
class NYPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new NYStyleCheesePizza();
        } else if ("pepperoni".equals(type)) {
            return new NYStylePepperoniPizza();
        }
        return null;
    }

// ConcreteCreator
class ChicagoPizzaStore extends PizzaStore {
    @Override
    Pizza createPizza(String type) {
        if ("cheese".equals(type)) {
            return new ChicagoStyleCheesePizza();
        } else if ("pepperoni".equals(type)) {
            return new ChicagoStylePepperoniPizza();
        }
        return null;
    }
}
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();

Pizza pizza = nyStore.orderPizza("cheese");
Pizza pizza1 = chicagoStore.orderPizza("pepperoni");

예제2

// RobotFactory 클래스 생성

public abstract class RobotFactory {
	abstract Robot createRobot(String name);
}
// SuperRobotFactory 클래스 생성

public class SuperRobotFactory extends RobotFactory {
	@Override
	Robot createRobot(String name) {
		switch(name) {
		case "super" :
			return new SuperRobot();
		case "power" :
			return new PowerRobot();
		}
		return null;
	}
}

➡️ 생성하는 객체를 별도로 두고 객체에 넘어오는 값에 따라서 다른 로봇(피자)를 만듦

[참고 자료]

🔗링크
🔗링크

0개의 댓글