공부/디자인 패턴

[디자인패턴] 추상 팩토리 패턴 (Abstract Factory Pattern)

감자 바보 2022. 3. 23. 16:10
반응형

추상 팩토리 패턴(Abstract Factory Pattern)

의도 : 구체화된 서브클래스 정의 없이 서로 관련 있는 객체 군 생성을 위한 인터페이스를 제공한다.

 

활용

  • 객체 생성, 구성 · 표현 방식 무관한 시스템을 독립적으로 만들 경우
  • 여러 제품군 중 하나만을 선택해 시스템을 설정해야 하며 이를 나중에 다른 것으로 대체할 수 있어야 하는 경우
  • 관련 객체들이 함께 사용되도록 설계되었고 이 제약이 지켜지도록 하고 싶을 경우
  • 제품의 라이브러리를 제공하고 제품의 구현이 아닌 인터페이스만을 노출시키고 싶을 경우

장점

  1. 구체적인 클래스 분리
  2. 제품군의 쉬운 교체
  3. 제품군 일관성 증진

단점

  1. 제품 추가의 어려움
    • 제품 추가가 될 시 팩토리를 모두 수정해주어야 함

예시

 한 소비자가 삼성과 애플 두 핸드폰 판매 브랜드의 핸드폰을 주문한다고 가정하자. 핸드폰 구성요소로는 디스플레이와 내부 장치가 존재하며 핸드폰에는 각 브랜드의 구성품이 사용되어야 한다.

 

UML

 

 핸드폰을 생산하는 공장 PhoneFactory 클래스, 내부 장치 InnenrDevice 클래스, 디스플레이 Display 클래스가 각각 가상 클래스로 존재하고 삼성과 애플은 위 세 클래스를 상속받아 사용한다면 위 UML과 같이 표현할 수 있다. 

 

 예시 코드의 흐름은 아래와 같다.

  1. 핸드폰을 만들기 위해 InnerDevice와 Display가 필요하다. InnerDevice는 키보드와 마이크를 테스트하는 testKeyboardInput과 testMicrophoneInput 메소드가메서드가 포함되는 추상 클래스이며 Display는 디스플레이를 테스트하는 testDisplay 메서드가 포함된 추상 클래스이다. 삼성과 애플은 이 두 클래스를 각각 상속받아 자신 브랜드의 InnerDevice와 Display를 개발한다.
    • Display
    • 더보기
      public abstract class Display {
          public Display() {
          }
          public abstract void testDisplay();
      }
      
      class SamsungDisplay extends Display {
          public SamsungDisplay() {}
      
          @Override
          public void testDisplay() {
              System.out.println("삼성 디스플레이 테스트");
          }
      }
      
      class AppleDisplay extends Display {
          public AppleDisplay() {}
      
          @Override
          public void testDisplay() {
              System.out.println("애플 디스플레이 테스트");
          }
      }
    • InnerDevice
    • 더보기
      public abstract class InnerDevice {
          public InnerDevice() {}
      
          public abstract void testKeyboardInput();
          public abstract void testMicrophoneInput();
      }
      
      class SamsungInnerDevice extends InnerDevice {
          public SamsungInnerDevice() {}
      
          @Override
          public void testKeyboardInput() {
              System.out.println("삼성 키보드 입력 테스트");
          }
      
          @Override
          public void testMicrophoneInput() {
              System.out.println("삼성 마이크 입력 테스트");
          }
      }
      
      class AppleInnerDevice extends InnerDevice {
          public AppleInnerDevice() {}
      
          @Override
          public void testKeyboardInput() {
              System.out.println("애플 키보드 입력 테스트");
          }
      
          @Override
          public void testMicrophoneInput() {
              System.out.println("애플 마이크 입력 테스트");
          }
      }
  2. PhoneFactory는 createInnerDevice와 createDisplay를 사용하여 InnerDevice와 Display를 생산한 뒤 이를 이용해 핸드폰을 생산한다. 삼성과 애플은 이를 상속받아 핸드폰 공장을 세우고, 자신 브랜드의 부품을 사용하도록 함수를 오버라이딩하여 사용한다. 
    • PhoneFactory
    • 더보기
      public abstract class PhoneFactory {
          public PhoneFactory() {};
          public abstract Display createDisplay();
          public abstract InnerDevice createInnerDevice();
      }
      
      class SamsungPhoneFactory extends PhoneFactory {
          public SamsungPhoneFactory() {}
      
          @Override
          public Display createDisplay() {
              return new SamsungDisplay();
          }
      
          @Override
          public InnerDevice createInnerDevice() {
              return new SamsungInnerDevice();
          }
      }
      
      class ApplePhoneFactory extends PhoneFactory {
          public ApplePhoneFactory() {}
      
          @Override
          public Display createDisplay() {
              return new AppleDisplay();
          }
      
          @Override
          public InnerDevice createInnerDevice() {
              return new AppleInnerDevice();
          }
      }
  3. 소비자는 메인함수에서 createDisplay 함수를 통해 대리점에서 핸드폰을 주문한다. 소비자에 주문대로 대리점은 samsungPhoneFactory와 applePhoneFactory를 통해 알맞는 핸드폰을 발주한다. 주문 받은 공장은 자기네 공정대로 폰을 생성하고 보내주게 됩니다. 예시에선 두 종류의 핸드폰 모두 주문하였다.
    • 메인 함수 및 주문(createPhone)
    • 더보기
      public class AbstarctFactoryProject {
          public static void main(String[] args) {
              SamsungPhoneFactory samsungPhoneFactory = new SamsungPhoneFactory();
              System.out.println("- 삼성 핸드폰 생산 - ");
              createPhone(samsungPhoneFactory);
      
              ApplePhoneFactory applePhoneFactory = new ApplePhoneFactory();
              System.out.println("\n- 애플 핸드폰 생산 - ");
              createPhone(applePhoneFactory);
          }
      
          public static void createPhone(PhoneFactory factory) {
              Display display = factory.createDisplay();
              display.testDisplay();
      
              InnerDevice innerDevice = factory.createInnerDevice();
              innerDevice.testKeyboardInput();
              innerDevice.testMicrophoneInput();
          }
      }

실행결과


마무리

 생성 패턴 중 하나인 추상 팩토리 패턴에 대해 학습하였다. 추상 팩토리 클래스는 팩토리 매서드 패턴이나 원형패턴, 그리고 단일체 팩턴 등을 사용한다고 한다. 이후 이러한 패턴을 학습할 때 복습할 필요가 있을 것 같다.


참고

에릭 감마, 리처드 헬름, 랄프 존슨, 존 블리시디스, 『GoF의 디자인 패턴』, 프로텍 미디어, 2015