카테고리 없음

[내일배움캠프] 3월 10일 금요일 TIL 회고록

tft4rollz 2023. 3. 11. 00:30

추상 팩토리 패턴

추상 팩토리 패턴은 연관성이 있는 객체 군이 여러개 있을 경우 이들을 묶어 추상화하고, 어떤 구체적인 상황이 주어지면 팩토리 객체에서 집합으로 묶은 객체 군을 구현화 하는 생성 패턴이다. 클라이언트에서 특정 객체을 사용할때 팩토리 클래스만을 참조하여 특정 객체에 대한 구현부를 감추어 역할과 구현을 분리시킬 수 있다.

즉, 추상 팩토리의 핵심은 제품 '군' 집합을 타입 별로 찍어낼수 있다는 점이 포인트 이다. 예를들어 모니터, 마우스, 키보드를 묶은 전자 제품군이 있는데 이들을 또 삼성 제품군이냐 애플 제품군이냐 로지텍 제품군이냐에 따라 집합이 브랜드 명으로 여러갈래로 나뉘게 될때, 복잡하게 묶이는 이러한 제품군들을 관리와 확장하기 용이하게 패턴화 한것이 추상 팩토리 이다.

 

추상 팩토리 구조

 

  • AbstractFactory : 최상위 공장 클래스. 여러개의 제품들을 생성하는 여러 메소드들을 추상화 한다.
  • ConcreteFactory : 서브 공장 클래스들은 타입에 맞는 제품 객체를 반환하도록 메소드들을 재정의한다.
  • AbstractProduct : 각 타입의 제품들을 추상화한 인터페이스
  • ConcreteProduct (ProductA ~ ProductB) : 각 타입의 제품 구현체들. 이들은 팩토리 객체로부터 생성된다. 
  • Client : Client는 추상화된 인터페이스만을 이용하여 제품을 받기 때문에, 구체적인 제품, 공장에 대해서는 모른다.
  •  

예제

스포츠 팀을 만든다고 가정하겠다. 스포츠 팀은 플레이어와 매니저가 꼭 필요하기에 팀의 구성요소라고 볼 수 있다.

public interface Manager {
}

public class SoccerManager implements Manager {
}

public class TennisManager implements Manager {
}

Manager 인터페이스와 클래스를 정의한다.  축구팀과 테니스팀이 존재하기에 두 개의 Manager 클래스를 정의한다.

 

public interface Player {
}

public class SoccerPlayer implements Player {
}

public class TennisPlayer implements Player {
}

Player 인터페이스와 클래스를 정의한다. 이것도 축구팀과 테니스팀이 존재하기에 두 개의 Player 클래스를 정의한다.

 

public interface BaseFactory {
  Player createPlayer();
  Manager createManager();
}

public class SoccerFactory implements BaseFactory {

  @Override
  public Player createPlayer() {
    return new SoccerPlayer();
  }

  @Override
  public Manager createManager() {
    return new SoccerManager();
  }
}

public class TennisFactory implements BaseFactory {

  @Override
  public Player createPlayer() {
    return new TennisPlayer();
  }

  @Override
  public Manager createManager() {
    return new TennisManager();
  }
}
  • Product 를 생성하는 Factory 클래스를 정의한다.
  • Manager, Player 는 축구, 테니스라는 하나의 공통점으로 묶을 수 있습니다.
  • 그래서 SoccerManager, SoccerPlayer 를 생산하는 SoccerFactory 와 반대로 테니스 객체들을 생성하는 TennisFactory 를 정의한다.
public class main {

  public static void main(String[] args) {
    BaseFactory factory = new SoccerFactory();

    Player player = factory.createPlayer();
    Manager manager = factory.createManager();

    player.receiveTraining();
    manager.makeDoWithTraining();

  }

}
  • 메인 클래스이다.
  • 구체 클래스가 아닌 인터페이스에 의존하게 작성할 수 있다.
  • 어떤 Factory를 넘겨받는지에 관계 없이 메인(클라이언트)는 Manager,Player를 생성할 수 있다.

SoccerFactory 객체로 실행 시

public class main {

  public static void main(String[] args) {
    BaseFactory factory = new TennisFactory();

    Player player = factory.createPlayer();
    Manager manager = factory.createManager();

    player.receiveTraining();
    manager.makeDoWithTraining();

  }

}

TennisFactory 객체로 실행 시 


의존 관계 다이어그램

선 제외하면 위에 사진이랑 똑같다...


장점과 단점

장점: 수정에는 닫혀있고 확장에는 열려있다.

단점 : 클래스 개수가 늘어난다.