Abstract Factory Pattern
많은 수의 연관된 서브 클래스를 특정 그룹으로 묶어(팩토리화)
한번에 교체할 수 있도록 만든 디자인 패턴
Example
PizzaStore
- 그걸 상속받는 서브 클래스 :
NYPizzaStore
,ChicagoPizzaStore
- 뉴욕가게와 시카고가게에서 Pizza(객체)를 만들 때 사용되는 재료들은 중복됨
- 두 가게 모두 도우, 소스, 토핑, 치즈가 필요
이러한 부분을 묶어서 팩토리화하는 것이 추상팩토리패턴
- 두 가게 모두 도우, 소스, 토핑, 치즈가 필요
⇒ 팩토리를 이용하여 피자에서 쓰이는 재료를 만드는 것
만들어지는 구체적인재료들은 어떤 팩토리를 쓰는지에 따라 달라짐
(ex) 도우 → 두꺼운 도우일지, 씬일지는 팩토리에 의해 결정됨)
PizzaIngredientFactory
public interface PizzaIngredientFactory {
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Pepperoni createPepperoni();
}
public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
public Dough createDough() {
return new ThinCrustDough();
}
public Sauce createSauce() {
return new MarinaraSauce();
}
public Cheese createCheese() {
return new ReggianoCheese();
}
public Pepperoni createPepperoni() {
return new SlicePepperoni();
}
public Clams createClam() {
return new FreshClams();
}
}
Pizza
public class CheesePizza extends Pizza {
PizzaIngredientFactory ingredientFactory;
public CheesePizza(PizzaIngredientFactory ingredientFactory) {
this.ingredientFactory = ingredientFactory;
}
voide prepare() {
System.out.println("Preparing " + name);
doug = ingredientFactory.createDough();
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
- Client단 구현 :
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);
}
public class NYPizzaStore extends PizzaStore {
protected Pizza createPizza(String item) {
Pizza pizza = null;
PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
if( item.equals("cheese") ) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("New York Style Cheese Pizza");
} else if( item.equals("clam") ) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("New York Style Clam Pizza");
} else if( item.equals("pepperoni") ) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("New York Style Pepperoni Pizza");
}
return pizza;
}
}
=>구상 클래스에 직접 의존하지 않고도 서로 관련된 객체들로 이루어진 제품군을 만들 수 있음
장단점
- 장점 : 구상 형식에 대한 의존을피하고 추상화 지향 가능
- 단점 : 새로운 ConcreteFactory를 추가할 때 많은 작업이 필요
정리
- Factory Method Pattern과 유사하면서도 사용 용도가 다름
- Abstract Factory Pattern에 Factory Method Pattern을 차용할 수도 있음
- 모든 팩토리의 공통점 : 객체 생성을 캡슐화해서 애플리케이션의 결합을 느슨하게 만들고, 특정 구현에 덜 의존이게 만든다
Factory Method Pattern과 차이점
- 결합도를 낮추는 대상
- 팩토리 메서드 패턴
- ConcreteProduct와 Client 간의 결합도를 낮출때 사용
- 추상 팩토리 패턴
- ConcreteFactory와 Client간의 결합도를 낮출 때 사용
- 팩토리 메서드 패턴
- Inheritance(상속), Composition(구성)
- 팩토리 메서드 패턴
- 상속을 사용하여 객체의 인스턴스 생성에 대해서는 서브클래스에 의존
- 지역 레퍼런스 없이 바로 하위 클래스의 함수를 호출하여 객체를 만듦
- 추상 팩토리 패턴
- 지역 레퍼런스를 두어 , 외부로부터 Factory 객체를 DI 받아서 위임
- 팩토리 메서드 패턴
Reference
https://jdm.kr/blog/192
https://flower0.tistory.com/416
https://beomseok95.tistory.com/246