본문 바로가기
소프트웨어공학/디자인 패턴

Abstract Factory Pattern - 생성, 팩토리 추상화와 제품군 생성 추상화 | 추상 팩토리 패턴 [Design pattern] 디자인 패턴

by javapp 자바앱 2021. 12. 26.
728x90

 

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의 인터페이스를 사용하여 제품군을 생성

 

 

 

 


 

 

 

diagram

 

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;
	}
}

pizzaaf.zip
0.01MB

 

댓글