Abstract Factory
다양한 구성 요소 별로 객체의 집합 생성
같은 종류의 여러 개의 객체를 생성할 수 있는 클래스를 생성
- 생성 군들을 하나에 모아놓고 팩토리(Factory) 중에서 선택하게 하는 패턴
- 관련있는 서브 클래스를 묶어서 팩토리 클래스를 만들고, 이들 조건에 따라 객체를 생성하는 패턴
- 여러 개의 클래스를 하나의 추상 클래스로 묶어 한번에 교체할 수 있는 패턴
ex) 제품군 (A family of products)
GUI widgets : window, scroll bar, button, text field ..
Pizza ingredients : dough, sauce, cheese ...
- 제품, 운영체제, 회사별로 유사한 제품이지만 지원하는 기능에 차이가 있을 경우, 기능별로 통합하여 운영할 떄 유리
문제점)
Client가 직접 concrete product class 를 사용하여 제품군을 생성했을 때,
현재 제품군을 다른 제품군으로 변경해야하는 경우, 여러 곳에서 생성한 경우
해결)
제품군 생성을 추상화하는 방법
- LSP : Client 가 생성에 사용된 conrete product class 가 무엇인지 모르게 한다.
- Abstract factory : 제품군의 각 제품을 생성을 위한 인터페이스를 제공
- Conrete factory : 자신의 제품군을 생성
- Client : abstract factory의 인터페이스를 사용하여 제품군을 생성
✓AbstractFactory : abstract product objects 생성 연산을 위한 interface를 명시한다.
✓AbstractProduct : 제품 객체 타입에 따른 interface 명시한다.
✓Client (or Composite product) : 오직 AbstractFactory and AbstractProduct classes에 의해 명시된 인터페이스들을 사용
예시)
팩토리 인터페이스
객체 생성을 추상화
피자에 들어가는 각각의 재료(성분) 객체 생성 메소드
// abstract factory
public interface PizzaIngredientFactory
{
// 제품군 ( a family of ingredients) 생성을 위한 interface 제공 - 객체 생성을 추상화
public Dough createDough();
public Sauce createSauce();
public Cheese createCheese();
public Veggies[] createVeggies();
public Pepperoni createPepperoni();
public Clams createClam();
}
피자 재료 구현 클래스
여러 피자 생성 클래스 중 하나를 예시
// concrete factory
public class ChicagoPizzaIngredientFactory implements PizzaIngredientFactory
{
// 특정 제품군을 생성, 객체 생성 !
// 특정 제품군에 대한 접근 제어 / 제공 (enforces automatically)
public Dough createDough() {
return new ThickCrustDough();
}
public Sauce createSauce() {
return new PlumTomatoSauce();
}
public Cheese createCheese() {
return new MozzarellaCheese();
}
public Veggies[] createVeggies() {
Veggies veggies[] = { new BlackOlives(),
new Spinach(),
new Eggplant() };
return veggies;
}
public Pepperoni createPepperoni() {
return new SlicedPepperoni();
}
public Clams createClam() {
return new FrozenClams();
}
}
Product
피자(제품군) 추상 클래스
public abstract class Pizza
{
String name;
// A family of ingredients(products)
Dough dough;
Sauce sauce;
Veggies veggies[];
Cheese cheese;
Pepperoni pepperoni;
Clams clam;
// creates a family of products
public abstract void prepare();
public void bake() {
System.out.println("Bake for 25 minutes at 350");
}
public void cut() {
System.out.println("Cutting the pizza into diagonal slices");
}
public void box() {
System.out.println("Place pizza in official PizzaStore box");
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String toString() { //... }
}
피자(제품군) 구현 클래스
(여러 피자 종류가 존재)
public class CheesePizza extends Pizza
{
// concrete factory 연관
PizzaIngredientFactory ingredientFactory;
// 연관 위임 주입
public CheesePizza(PizzaIngredientFactory ingredientFactory) { // 주입
this.ingredientFactory = ingredientFactory;
}
public void prepare() {
System.out.println("Preparing " + name);
// creates a product family using abstract factory's interface
dough = ingredientFactory.createDough(); // 위임
sauce = ingredientFactory.createSauce();
cheese = ingredientFactory.createCheese();
}
}
주입을 통해 팩토리 클래스를 구성하고 위임
스토어
public abstract class PizzaStore
{
// 피자 객체 생성
// item : 피자 종류
protected abstract Pizza createPizza(String item);
// 피자 주문
public Pizza orderPizza(String type) {
Pizza pizza = createPizza(type);
System.out.println("--- Making a " + pizza.getName() + " ---");
pizza.prepare();
pizza.bake();
pizza.cut();
pizza.box();
return pizza;
}
}
public class ChicagoPizzaStore extends PizzaStore
{
protected Pizza createPizza(String item)
{
// 피자, 팩토리 객체 생성
Pizza pizza = null;
// creating its own factory , Or injected by 3rd party
PizzaIngredientFactory ingredientFactory = new ChicagoPizzaIngredientFactory();
if (item.equals("cheese")) {
pizza = new CheesePizza(ingredientFactory);
pizza.setName("Chicago Style Cheese Pizza");
} else if (item.equals("veggie")) {
pizza = new VeggiePizza(ingredientFactory);
pizza.setName("Chicago Style Veggie Pizza");
} else if (item.equals("clam")) {
pizza = new ClamPizza(ingredientFactory);
pizza.setName("Chicago Style Clam Pizza");
} else if (item.equals("pepperoni")) {
pizza = new PepperoniPizza(ingredientFactory);
pizza.setName("Chicago Style Pepperoni Pizza");
}
return pizza;
}
}
댓글