[기존 코드의 문제점]
: 다음과 같이 실행시의 주어진 조건에 따라 생성되는 구상 클래스 코드가 있을때.
Duck duck;
if (picnic) {
duck = new MallardDuck();
} else if (hunting) {
duck = new DecoyDuck();
} else if (inBathTub) {
duck = new RubberDuck();
}
: 코드의 변경 및 확장할때 복잡해져 관리 및 갱신이 어려워진다.
# 무엇이 문제인가?
: 변화에 대해 닫혀 있는 코드의 모습
# 팩토리 패턴의 기본 구조
# 팩토리 패턴 예제 1 - 피자 가게
[1단계]
: SimplePizzaFactory로 피자 종류 선택하는 코드 분리만 해준 상태이다.
- PizzaStory 클래스 : factory에서 생성해줄 피자종류 받아와 공통 작업 수행(prepare, bake, cut, box)
public class PizzaStore {
PizzaFactory pizzaFactory;
public PizzaStore(PizzaFactory pizzaFactory){
this.pizzaFactory = pizzaFactory;
}
Pizza orderPizza(String type) { // type에 따라 만드는 피자 종류 달라진다
// pizzafactory로 피자타입 선택하는 코드 분리해줘서 작성해야 하는 코드
Pizza pizza;
pizza = pizzaFactory.createPizza(type);
// 공통된 부분(바뀌지 않는 부분)
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
- (Simple)PizzaFactory 클래스 : 주어진 type에 따라 생성할 피자 종류 선택 (아직 개선 필요한 형태)
public class PizzaFactory {
public Pizza createPizza(String type){
Pizza pizza = null;
// 피자 추가 및 변경시 이 코드 일일히 수정해야한다.
if (type.equals("cheese")){
pizza = new CheesePizza();
} else if (type.equals("greek")){
pizza = new GreekPizza();
} else if (type.equals("pepperoni")){
pizza = new PepperoniPizza();
}
return pizza;
}
}
- Pizza 클래스와 그 자식 클래스 : 생략. (prepare, bake, cut, box) 구현 필수
* 이상태만으론 패턴이라 할 수 없다(if문 만연..)
[2단계](파일로 존재)
: 아래 코드에서는 Pizza의 중간 코드 없이 바로 피자종류클래스가 상속받는 구조로 되어있으니 유의!
- PizzaStore 클래스 : Creator 클래스
public abstract class PizzaStore {
void prepareToBoxing(Pizza pizza){ // 공통작업
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
}
Pizza orderPizza(String type) {
Pizza pizza;
pizza = createPizza(type); //팩토리객체가 아닌 pizzastore에서 호출
prepareToBoxing(pizza);
return pizza;
}
abstract Pizza createPizza(String type);
// 각 피자 가게지점에서 각 지점별 특색 피자들 만들기위해 추상화함.
}
- NYPizzaStore 클래스 : ConcreteCreator 클래스
public class NYPizzaStore extends PizzaStore {
Pizza createPizza(String type){
Pizza pizza = null;
if (type.equals("cheese")) {
pizza = new NYStyleCheesePizza();
} else if (type.equals("pepperoni")) {
pizza = new NYStylePepperoniPizza();
} else if (type.equals("clam")) {
//pizza = new NYStyleClamPizza();
} else if (type.equals("veggie")) {
//pizza = new NYStyleVeggiePizza();
}
return pizza;
}
}
- Pizza 클래스 : Product 클래스
import java.util.ArrayList;
public abstract class Pizza {
String name;
String dough;
String sauce;
ArrayList toppings = new ArrayList();
void prepare(){
System.out.println( name+" 피자 준비중...");
System.out.println("도우 전달중...");
System.out.println("소스 추가중...");
System.out.println("토핑 추가중 : ");
for (int i = 0; i < toppings.size(); i++) {
System.out.println(" " + toppings.get(i));
}
}
void bake(){
System.out.println("피자 굽는중...");
}
void cut(){
System.out.println("피자 자르는중...");
}
void box(){
System.out.println("피자 포장중...");
}
public String getName(){
return name;
}
}
- NYStylePepperoniPizza 클래스 : ConcreteProduct 클래스
public class NYStylePepperoniPizza extends Pizza{
NYStylePepperoniPizza(){
name = "뉴욕 스타일 소스와 페퍼로니 피자";
dough = "얇고 크런치한 도우";
sauce = "토마토 소스";
toppings.add("토핑없음");
}
}
[3단계](원재료 생산 공장) - 추상 팩토리 패턴
: 원재료를 생산하는 팩토리 생성 (코드 생략, 파일로 있음)
# 팩토리 패턴 예제 2 - IDcard와 소유자 생성 공장
: 예제에선 추상클래스인 product와 factory를 framework라는 패키지 안에 넣었고
: IDCard(ConcreteProduct)와 IDCardFactory(ConcreteFactory)는 idcard 패키지에 넣었다.
: 또한 concrete끼리 참조하지 않고, 위 추상클래스끼리 참조하는 방식으로 작성되었다.
# 코드 생략, 단, 파일엔 존재
# 팩토리패턴 예제 3 - Observer 패턴예제를 팩토리 패턴으로
: observer역할의 window들을 종류에 따라 메인 panel에 추가할때, factory이용해서 어떤종류의 observer를 추가할지 설정
- OvserverWindowFactory(Creater 클래스)
- ConcreteObserverWindowFactory(ConcreteCreater 클래스)
: 여기서 concreteCreater가 들어온 str값과 일치하는 product 선택해주는 코드 존재
- ObserverWindow(Product 클래스)
- LabelWindow, TextFieldWindow(Concrete 클래스)
: 코드 파일로 존재.
'기타 > [고급객체지향 프로그래밍]' 카테고리의 다른 글
디자인 패턴 6강. 커맨드 패턴(Command Pattern) (0) | 2019.12.10 |
---|---|
디자인 패턴 5강. 싱글턴 패턴(Singleton Pattern) (0) | 2019.12.06 |
디자인 패턴 3강. Decorator 패턴 (0) | 2019.10.21 |
디자인 패턴 2강. Observer 패턴 (0) | 2019.10.20 |
디자인 패턴 1강. Strategy 패턴 (0) | 2019.10.18 |