
팩토리 메서드 패턴(Factory Method Pattern)은 객체 생성의 책임을 메서드로 분리하고,
이를 추상클래스나 인터페이스에 정의하여 구체적인 구현 클래스에서
객체 생성의 세부사항을 결정하도록 하는 디자인 패턴
SimplePizzaFactory는 현재 하나의 종류만 만들 수 있음 → 지역 별 스타일 반영 불가NY Style, CHI Style, CAL Style 각각의 CheesePizza 를 만들 수 없음!
NYPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.order("Veggie");
ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
PizzaStore nyStore = new PizzaStore(ChicagoFactory);
chicagoStore.order("Veggie"); ⚠ 구상 클래스에 의존하는 코드가 됨SimpleFactory로 분리한 createPizza() 를 다시 PizzaStore로 가지고 옴,PizzaStore에서 하지 않음PizzaStore를 상속 받는 구상 클래스에서 createPizza() 를 구현factoryMethod를 구현한다
Product : 팩토리 메서드가 생성할 객체의 인터페이스나 추상 클래스. 기존의 Pizza 추상클래스에 해당ConcreteProduct : 추상 제품을 구현하는 구체적인 클래스. 기존의 Cheese, Veggie Pizza 등 해당Creator : 팩토리 메서드를 정의하는 추상 클래스. 기존의 PizzaStore에 해당.factoryMethod() 를 추상 메서드로 선언ConcreteCreator : 추상팩토리를 상속하고, 팩토리메서드를 구현하여 객체생성을 책임지는 클래스
PizzaStore 에서 createPizza() 를 사용하여 원하는 스타일의 피자를 생성해서 주문에 대응NYPizzaStore ,ChicagoPizzaStore : 어떤 스타일의 피자를 생성할지 결정Pizza : Product에 해당NYStyleCheesePizza, ChicagoStyleCheesePizza … : ConcreteProduct에 해당PizzaStore 코드public abstract class PizzaStore {
protected abstract Pizza createPizza(String type);
// 팩토리 메서드. 서브클래스에서 객체 생성을 책임져야 함
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
// 어떤 피자가 만들어지는 지 알 수 없다.
// 즉, 실제로 생성되는 구상 객체가 무엇인지 알 수 없게 한다.
// 신기하게도 이 상태로 컴파일이 가능하다!
System.out.println("---Making a " + pizza.getName() + "---");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
pizza.deliver();
return pizza;
}
}
NYPizzaStore, CHIPizzaStore 코드public class NYPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new NYStyleCheesePizza();
} else if (type.equals("veggie")) {
return new NYStyleVeggiePizza();
} else {
return null;
}
}
}
```
```java
public class CHIPizzaStore extends PizzaStore {
@Override
protected Pizza createPizza(String type) {
if (type.equals("cheese")) {
return new CHIStyleCheesePizza();
} else if (type.equals("veggie")) {
return new CHIStyleVeggiePizza();
} else {
return null;
}
}
}
🔔 새로운 스타일의 피자를 추가하려면
PizzaStore를 상속받는 새로운 클래스와 해당 클래스에서createPizza메서드를 구현하면 된다. ex)ItalyPizzaStore
→ 클라이언트 코드는 변경할 필요 없이 새로운 피자 스타일을 사용할 수 있게 된다!
📌 이러한 방식으로 새로운 피자 스타일을 쉽게 추가할 수 있으며, 기존 코드의 수정 없이도 확장성을 유지할 수 있다
TestDriver 코드public class TestDriver {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chiStore = new CHIPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("Ethan 주문 " + pizza.getName() + "\n");
pizza = chiStore.orderPizza("cheese");
System.out.println("Joel 주문 " + pizza.getName() + "\n");
pizza = nyStore.orderPizza("veggie");
System.out.println("Ethan 주문 " + pizza.getName() + "\n");
pizza = chiStore.orderPizza("veggie");
System.out.println("Joel 주문 " + pizza.getName() + "\n");
}
}