책너두 (헤드 퍼스트 디자인 패턴) 11일차 (~165p)
- Book/헤드 퍼스트 디자인 패턴
- 2023. 7. 10.
요약
- 객체지향 빵 굽기 : 팩토리 패턴
- 다양한 팩토리 만들기
- 서브클래스가 결정하는 것 알아보기
- 피자 스타일 서브클래스 만들기
- 팩토리 메소드 선언하기
- 피자 팩토리 메소드로 피자 주문하기
- Pizza 클래스 만들기
- 최첨단 피자 코드 테스트
- 팩토리 메소드 패턴 살펴보기
- 생산자 클래스
- 제품 클래스
메모
다양한 팩토리 만들기
- 각 지점마다 그 지역의 특성과 입맛을 반영한 다양한 스타일의 피자를 만든다면?
- 피자 프랜차이즈 사업을 시작한다.
- SimplePizzaFactory를 삭제하고, NyPizzaFactory, ChicagoPizza, CaliforniaPizzaFactory를 만들어야 함.
- PizzaStore는 적당한 팩토리를 사용하도록 한다.
NyPizzaFactory nyFactory = new NYPizzaFactory();
PizzaStore nyStore = new PizzaStore(nyFactory);
nyStore.orderPizza("Veggie");
ChicagoPizzaFactory chicagoFactory = new ChicagoPizzaFactory();
PizzaStore chicagoStore = new PizzaStore(chicagoFactory);
chicagoStore.orderPizza("Veggie");
- PizzaStore 를 생성할때, 각 지점의 팩토리를 만들어준다.
- 만약, 굽는 방식이 달라지거나, 피자를 자르는 걸 까먹거나, 이상한 피자 상자를 쓴다면?
- 이 문제를 해결하려면 PizzaStore와 피자 제작 코드 전체를 하나로 묶어줘야 함.
- 유연성을 가져가면서도 피자 가게와 피자 만드는 과정을 하나로 묶는 방법은?
피자 가게 프레임워크 만들기
- 피자 만드는 일 자체를 전부 PizzaStore 클래스에 진행하면서, 지점의 스타일도 살릴 수 있음.
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
abstract Pizza createPizza(String type);
}
- PizzaStore 를 추상 클래스로 바꾼다.
- createPizza 메소드를 추상 메소드로 만든다. (팩토리 객체 대신 추상 메소드로 대체)
서브클래스가 결정하는 것 알아보기
- PizzaStore 의 orderPizza 메소드를 통해 이미 주문 시스템은 잘 갖춰져 있고 서브 클래스는 잘 사용만 하면 됨.
- 서브 클래스는 creatPizza 메소드를 구현해야 함.
- PizzaSroe 의 orderPizza 메소드는 실제로 어떤 구상 클래스에서 작업이 처리되는지 알 수 없음.
- 즉, PizzaStore 와 Pizza는 서로 완전히 분리됨.
- orderPizza 에서 createPizza 메소드가 호출되면 Pizza 서브 클래스가 그 호출을 받아서 피자를 만듦.
- 피자 가게에 따라 다른 종류의 피자가 만들어짐.
- 즉, 피자의 종류는 어떤 서브클래스를 선택했느냐에 따라 결정됨.
피자 스타일 서브클래스 만들기
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String item) {
if (item.equals("cheese") {
return new NYStyleCheesePizza();
} else if (item.equals("veggie")) {
return new NYStyleVeggiePizza();
} else if (item.equals("clam")) {
return new NYStyleClamPizza();
} else if (item.equals("pepperoni")) {
return new NYStylePepperoniPizza();
}
}
}
- 각 지점에서 PizzaStore 서브 클래스를 만들어서 지역별 특성에 맞게 createPizza() 메소드만 구현하면 됨.
팩토리 메소드 선언하기
public abstract class PizzaStore {
public Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type);
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
protected abstract Pizza createPizza(String type);
}
- Pizza 인스턴스를 만드는 일은 팩토리 메소드에서 맡아서 처리함.
- 피자 객체 인스턴스를 만드는 일은 PizzaStore 서브 클래스에 있는 createPizza() 메소드에서 처리함.
- 팩토리 메소드는 객체 생성을 서브클래스에 캡슐화할 수 있음.
- 슈퍼클래스에 있는 클라이언트 코드와 서브클래스에 있는 객체 생성 코드를 분리할 수 있음.
abstarct Product factoryMethod(String type)
- 팩토리 메소드를 추상 메소드로 선언해서 서브클래스가 객체 생성을 책임지도록 함.
- 팩토리 메소드는 특정 객체를 리턴하며, 그 객체는 보통 슈퍼클래스가 정의한 메소드 내에서 쓰임.
- 팩토리 메소드는 클라이언트에서 실제로 생성되는 구상 객체가 무엇인지 알 수 없게 만드는 역할도 함.
- 팩토리 메소드를 만들 때 매개변수로 만들 객체 종류를 선택할 수도 있음.
피자 팩토리 메소드로 피자 주문하기
- 뉴욕 스타일 피자와 시카고 스타일 피자를 주문한다.
- NyPizzaStore 가 필요함.
PizzaStore nyPizzaStore = new NYPizzaStore();
- 주문을 받을 수 있음.
nyPizzaStore.orderPizza("cheese");
- orderPizza() 메소드에서 createPizza() 메소드를 호출함.
Pizza pizza = createPizza("cheese");
- 이 경우, 뉴욕 스타일 치즈 피자가 만들어짐.
- 아직 준비되지 않은 피자를 받았으니, 피자 만드는 작업을 마무리 한다.
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
- 피자가 어떤 구상 클래스의 객체인지 전혀 알지 못함.
Pizza 클래스 만들기
public abstract class Pizza {
String name;
String dough;
String sauce;
List<String> toppings = new ArrayList<String>();
void prepare() {
System.out.println("준비 중: " + name);
System.out.println("도우를 돌리는 중...";
System.out.println("소스를 뿌리는 중...";
System.out.println("토핑을 올리는 중...";
for (String topping : toppings) {
System.out.println(" " + topping);
}
}
void bake() {
System.out.println("175도에서 25분 간 굽기");
}
void cut() {
System.out.println("피자를 사선으로 자르기");
}
void box() {
System.out.println("상자에 피자 담기");
}
public String getName() {
return name;
}
}
- 추상 클래스인 Pizza 임
public class NYStyleCheesePizza extends Pizza {
public NYStyleCheesePizza() {
name = "뉴욕 스타일 소스와 치즈 피자";
dough = "씬 크러스트 도우";
sauce = "마리나라 소스";
toppings.add("2270 22");
}
}
public class ChicagoStyleCheesePizza extends Pizza {
public ChicagoStyleCheesePizza() {
name="시카고 스타일 딥 디쉬 치즈 피자";
dough = "아주 두꺼운 크러스트 도우";
sauce = "플럼토마토 소스";
toppings.add("잘게 조각낸 모짜렐라 치즈");
}
void cut() {
System.out.println("4498 ");
}
}
- 구상 서브 클래스인 뉴욕 스타일 치즈 피자와 시카고 스타일 치즈 피자임.
최첨단 피자 코드 테스트
public class PizzaTestDrive {
public static void main(String[] args) {
PizzaStore nyStore = new NYPizzaStore();
PizzaStore chicagoStore = new ChicagoPizzaStore();
Pizza pizza = nyStore.orderPizza("cheese");
System.out.println("+" + pizza.getName() + "\n");
pizza chicagoStore.orderPizza("cheese");
System.out.println("0" + pizza.getName() + "\n");
}
}
팩토리 메소드 패턴 살펴보기
- 모든 팩토리 패턴은 객체 생성을 캡슐화 함.
- 팩토리 메소드 패턴은 서브클래스에서 어떤 클래스를 만들지 결정함으로써 객체 생성을 캡슐화 함.
생산자(Creator) 클래스
- 추상 생산자 클래스 : PizzaStore
- 서브 클래스에서 객체를 생산하려고 구현하는 팩토리 메소드를 정의 함.
- 구상 생산자 클래스(concrete creator) → 팩토리 메소드를 구현함. → 객체를 생산함.
제품(Prodcut) 클래스
- 생산 대상이 되는 객체임.
'Book > 헤드 퍼스트 디자인 패턴' 카테고리의 다른 글
책너두 (헤드 퍼스트 디자인 패턴) 13일차 (~189p) (0) | 2023.07.11 |
---|---|
책너두 (헤드 퍼스트 디자인 패턴) 12일차 (~179p) (0) | 2023.07.10 |
책너두 (헤드 퍼스트 디자인 패턴) 10일차 (~152p) (0) | 2023.07.08 |
책너두 (헤드 퍼스트 디자인 패턴) 9일차 (~139p) (0) | 2023.07.07 |
책너두 (헤드 퍼스트 디자인 패턴) 8일차 (~125p) (0) | 2023.07.06 |