-
디자인 패턴 (5) - 추상 팩토리 패턴언어/디자인패턴 2023. 9. 11. 14:09
1. 추상 팩토리 패턴이란?
- 연관성 있는 객체 군이 여러개 있을 경우 이를 묶어 추상화
- 구체적 상황이 주어지면, 팩토리 객체를 통해 객체 군을 구현화 하는 생성 패턴이다.
- 핵심은 제품군 집합을 타입별로 찍어낼 수 있다는 점이다.
1.1 추상 팩토리 패턴 구조
1. AbstractFactory: 최상위 공장 클래스 -> 여러 제품군을 생성하는 여러 메서드를 포함
2. ConcreteFactory: 서브 공장 클래스들은 타입에 맞는 제품 객체 반환하도록 메소드 오버라이딩
3. AbstractProduct: 각 제품군을 추상화 (대분류)한 인터페이스
4. ConcreteProduct : 각 타입 제품의 구현체 -> 팩토리를 통해 생성됨
5. Client : 추상화된 인터페이스만으로 제품을 받으므로, 구체적인 타입은 모른다.
1.2 Abstract Factory VS Factory Method
- 둘다 구체적인 타입은 감추고 객체를 생성하는 패턴 유사
- 팩토리 메서드 패턴은 객체 생성 이후 해야할 일의 공통점 정의 초점
- 추상 팩토리 패턴은 객체 집합 군의 공통점에 초점
* 팩토리 메서드 패턴은 구체적인 생성과정을 클래스로 옮기는 것이 목적 (여러 팩토리가 하나의 카테고리 생성)
추상 팩토리 메서드 패턴은 팩토리가 여러 제품군 생성을 지원
* 팩토리 패턴은 주로 상속을 통해 추상 팩토리 메서드 패턴은 주로 구성을 통해 만든다 (의존관계)
1.3 예시
- 제품군 정의 (추상화하여 구현체 분리)
interface AbstractProductA{ //카테고리 (버섯) } class ConcreteProductA1 implements AbstractProductA{ //구현체 (카테고리 별 실제 제품) (느타리버섯) } class ConcreteProductA2 implements AbstractProductA{ //(팽이버섯) } interface AbstractProductB{ //카테고리 (나무) } class ConcreteProductB1 implements AbstractProductB{ //(고목나무) } class ConcreteProductB2 implements AbstractProductB{ //(미루나무) }
- 공장클래스
interface AbstractFactory{ AbstractProductA createProductA(); //버섯 중 하나 생성 AbstractProductB createProductB();// 나무 중 하나 생성 } class ConcreteFactory1 implements AbstractFactory{ //느타리 미루 공장 public AbstractProductA createProductA(){ //버섯 중 하나 리턴 return new ConcreteProductA1(); // 느타리 } public AbstractProductB createProductB(){ //나무 중 하나 리턴 return new ConcreteProductB2();//미루나무 } class ConcreteFactory2 implements AbstractFactory{ // 팽이 고목 공장 public AbstractProductA createProductA(){ //버섯 중 하나 리턴 return new ConcreteProductA2(); // 팽이 } public AbstractProductB createProductB(){ //나무 중 하나 리턴 return new ConcreteProductB1();//고목나무 } }
1.5 추상 팩토리 패턴 특징
- 사용 시기: 관련 제품의 다양한 제품군과 함께 동작시
여러 제품군 중 하나 선택해서 시스템 설정해야할 때 (한번에 구성한 제품이 달라야함)
제품에 대한 라이브러리 제공하고, 구현이 아닌 인터페이스 노출
- 장점: 결합도 낮춤, 제품 군 교체가 쉽다,SRP,OCP준수
- 단점: 클래스 너무 많아짐, 새로운 제품 대분류 생성이 어렵다 (많이 고쳐야함), 세부사항이 변경되면 모든 팩토리 수정이 필요
*초기설정 + 설정 하는 클래스 다양성이 일정할 때 쓰자
2. 피자 원재료 팩토리 만들기
- 지점별로 원재료가 달라짐
public interface PizzaIngredientFactory{ public Dough createDough(); // 대분류 public Sauce createSauce(); //.. 각 재료별 팩토리용 인터페이스 }
public class NYPizzaIngredientFactory implements PizzaIngredientFactory{ public Dough createDough(){ return new ThinCrustDough(); //구체 타입 리턴 } public Sauce createSauce(){ return new MarinarSauce(); } //여러 재료들 한번에 설정 }
- Pizza 객체
public abstract class Pizza{ String name; Dough dough; //..피자재료 abstract void prepare(); // 피자만들 때 필요한 재료들을 원재료 팩토리에서 가져올 것 //기존 코드와 달라진점 -> 피자원재료 팩토리 추가해서 한번에 재료 설정할 것 } public class CheesePizza extends Pizza{ PizzaIngredientFactory ingredientFactory; //재료군에서 구체 재료를 생성할 팩토리 public CheesePizza(PizzaIngridientFactory i){ this.ingredientFactory = i; } void prepare(){ i.createDough();//등 } }
- Pizza Store
public class NYPizzaStore extends PizzaStore{ protected Pizza createPizza(String item){ Pizza pi = null; PizzaIngredientFactory in = new NYCPizzaIngredientFactory(); //구현체 전달 if(item.equals("chees")){ pizza = new CheesePizza(ingredientFactory); //피자 원재료 팩토리 전달 } //if문 돌면서 pizza찾기 } } // 피자 팩토리가 생성과 동시에 원재료 팩토리도 지정
참고자료:
헤드 퍼스트 디자인 패턴 (한빛미디어)
'언어 > 디자인패턴' 카테고리의 다른 글
디자인 패턴 (7) - 커맨드 패턴 (0) 2023.09.12 디자인 패턴 (6) - 싱글톤 패턴 (0) 2023.09.11 디자인 패턴 (4) - 팩토리 패턴 (0) 2023.09.11 디자인패턴 (3) - 데코레이터패턴 (0) 2023.09.08 디자인 패턴 (2) - 옵저버 패턴 (0) 2023.09.08