개발자이야기
추상팩토리 패턴 (Abstract-Factory Pattern) 본문
추상팩토리패턴
추상 팩토리 패턴(Abstract factory pattern)은 다양한 구성 요소 별로 객체의 집합을 생성해야 할 때 유용하다. 이 패턴을 사용하여 상황에 알맞은 객체를 생성할 수 있다.
위의 내용이 무엇일까??
재료의 공장을 만든다고 생각해봅시다.
예제에서 설명하고자 하는 재료의 공장은 두가지 입니다. 롯데리아 공장, 맥도날드 공장.
각각의 공장에서 하는 일은 같습니다. 재료를 전달해준다.
햄버거의 만드는 과정
1. 고객의 햄버거 주문
2. 주문에 의한 버거메뉴 조리
3. 공장에서의 재료 조달
간단하게 위와같이 3단계의로 나누어 보았습니다. 이제 예제로 한번 살펴봅시다.
코드는 위의 과정을 역순으로 올라가 보겠습니다.
3. 공장에서의 재료 조달
public interface IngredientFactory {
public Bread createBread();
public Patty createPatty(String type);
public Vegetable createVegetable();
public Sauce createSauce();
}
햄버거 재료를 만드는 공장을 정의(추상화) 해 놓은 것 입니다.
햄버거의 필수 재료인 빵을 절달 해 주어야 하며, 패티와 야채 그리고 소스가 필요 합니다.
위의 interface를 구현한 클래스를 보겠습니다.
public class LotteriaFactory implements IngredientFactory {
@Override
public Bread createBread() {
return new LotteriaBread();
}
@Override
public Patty createPatty(String type) {
if ("치킨".equals(type)) {
return new LotteriaChickenPatty();
}
return new LotteriaBulgogi();
}
@Override
public Vegetable createVegetable() {
return new Tomato();
}
@Override
public Sauce createSauce() {
return new Mustard();
}
}
LotteriaFactory(롯데리아 공장)
추상화 되어있는 재료공장을 구현하고 있습니다. 여기서 추상팩토리가 왜 쓰이는가에 대해 우선 짚고 넘어가 보겠습니다. 어떤 객체든 상황에 따른 객체의 집합이 필요하기 마련입니다. 위의 예처럼 롯데리아에서는 롯데리아 공장에 있는 빵, 패티, 야채, 소스를 고정적으로 공급 받을 것 입니다.
마찬가지로 맥도날드 가게에선 맥도날드 전용 재료 공장에서 재료들을 똑같이 공급받겠죠.(물론 실제론 그러지 않을수도 있습니다.)
2. 주문에 의한 버거메뉴 조리
public interface Store {
Hamburger createHamburger(String type);
}
public class Lotteria implements Store {
IngredientFactory factory;
public Lotteria(IngredientFactory factory) {
this.factory = factory;
}
@Override
public Hamburger createHamburger(String type) {
BurgerFactory burgerFactory = new BurgerFactory(factory);
return burgerFactory.burger(type);
}
}
가게로 주문이 들어왔습니다 (createHamburger(String type)).
createHamburger 메소드를 확인해 보겠습니다.
- 팩토리 메소드 패턴
고객으로부터 주문이 들어와 햄버거를 만드는 과정에 팩토리 메소드 패턴이 들어갔습니다. 앞으로도 Lotteria 클래스에선 어떤 메뉴가 추가되더라도 수정될 필요가 없이 BurgerFactory 클래스에 추가만 해주면 됩니다.
Lotteria -> 데리버거
Lotteria -> 크리스피버거
Lotteria -> 기타등등버거
위와같은 의존성을 바꿔줘야 합니다.
Lotteria -> Hamburger
데리버거 -> Hamburger
크리스피버거 -> Hamburger
기타등등버거 -> Hamburger
위와같이 바뀐것입니다. 쓸데없는 설명일 수 있으나 언제나 의존관계를 느슨하게 해주어야 합니다.
public class BurgerFactory {
IngredientFactory factory;
public BurgerFactory(IngredientFactory factory) {
this.factory = factory;
}
public Hamburger burger(String burgerType) {
switch (burgerType) {
case "데리버거":
return new Derryburger(factory);
case "크리스피버거":
return new CrispyBurger(factory);
default:
return new BasicBurger(factory);
}
}
}
자 이제 위의 버거를 만들어 제공해주는 팩토리를 한번 살펴보겠습니다.
아래의 코드는 DerryBurger 클래스 입니다.
public class Derryburger extends Hamburger {
IngredientFactory factory;
public Derryburger(IngredientFactory factory) {
this.factory = factory;
makeBurger();
}
@Override
protected void prepare() {
bread = factory.createBread();
patty = factory.createPatty("데리버거 고기");
sauce = factory.createSauce();
}
}
DerryBurger 클래스는 Hamburger 추상클래스를 상속받고 있습니다. 위의 생성자를 보면 IngredientFactory interface를 넘겨받는 것을 볼 수 있습니다. 여기서 재료 공장(LotteriaFactory)에서의 재료를 받아 데리버거를 만들게 됩니다.
public abstract class Hamburger {
public Bread bread;
public Patty patty;
public Sauce sauce;
private void cook() {
System.out.println("조리시작 칙칙");
System.out.println(patty.meat() + "패티를 " + bread.breadType() + "에 넣고");
System.out.println(sauce.sauce() + "를 뿌린다");
System.out.println("햄버거 완성!");
}
public final void makeBurger() {
prepare();
cook();
}
protected abstract void prepare();
}
Hamburger 추상 클래스 입니다. 템플릿 메소드 패턴으로 구현했습니다. 앞으로 어떤 버거를 만들더라도 prepare() 메소드만 서브 클래스에서 잘 구현해 준다면 햄버거는 잘 완성되겠네요!
public class Creator {
public static void main(String[] args) {
Store lotteria = new Lotteria(new LotteriaFactory());
lotteria.createHamburger("데리버거");
}
}
조리시작 칙칙
데리버거패티를 롯데리아 빵에 넣고
머스타드를 뿌린다
햄버거 완성!
추상팩토리 패턴을 알아봤습니다. 최대한 공부하며 이해를 토대로 작성하려 했으나 이해가 부족한 부분으로 잘못된 부분이 있을 수 있습니다. 언제든 피드백은 환영하고 지적해주셔도 됩니다.
앞으로도 디자인패턴은 공부하여 계속해서 포스팅을 할 것입니다. 사실 업무를 하며 이번엔 추상팩토리를 써보자! 하고 도입하는경우는 흔치 않을거라 생각합니다. 보통 개발자의 스타일대로 자신만의 디자인 패턴을 만들어 쓰는경우도 흔하니까요.
하지만 이런 디자인 패턴을 공부 함으로써 왜 객체간의 의존성을 줄이기 위해 이런 노력을 하는지 알 수 있게되는 것 같습니다.
읽어주셔서 감사합니다.
'디자인패턴' 카테고리의 다른 글
디자인패턴 Adapter pattern (0) | 2021.09.02 |
---|---|
의존성 주입(dependency injection) (0) | 2021.06.17 |
팩토리 메소드 패턴 (Factory method pattern) (0) | 2021.06.09 |
템플릿 메소드 (Template method) 패턴 (0) | 2021.06.09 |