[디자인 패턴] Abstract Factory

Creational Pattern - Abstract Factory

📚 의도

상세화된 서브클래스를 정의하지 않고도 서로 관련성이 있거나 독립적인 여러 객체의 집합을 생성하기 위한 인터페이스를 제공합니다.(GoF)

기본이 되는 Factory가 재료를 공급하며, 생산된 Product가 정확히 무엇인지 알지 못해도 Product의 인터페이스만 알면 조작할 수 있다.

  • 예시
    • 연관 있는 제품의 집합: {Monitor + Keyboard + Mouse}
    • 제품 집합의 변형(제품들을 만드는 회사):
      • Samsung{Monitor + Keyboard + Mouse}
      • LG{Monitor + Keyboard + Mouse}
      • Apple{Monitor + Keyboard + Mouse}

🧱 구조

  1. Abstract Products : ProductA, ProductB
    • 모니터, 키보드, 마우스 interface
  2. Concrete Products : ConcreteProductA1, ConcreteProductA2 / ConcreteProductB1, ConcreteProductB2
    • 삼성 모니터, LG 모니터 / 삼성 키보드, LG 키보드
  3. Abstract Factory : createProductA():ProductA, createProductB():ProductB
    • 모니터를 생산한다, 키보드를 생산한다, 마우스를 생산한다
  4. Concrete Factories :createProductA():ConcreteProductA1, createProductB():ConcreteProductB1
    • 삼성 팩토리: 삼성 모니터를 생산한다, 삼성 키보드를 생산한다, 삼성 마우스를 생산한다.
    • LG 팩토리: LG 모니터를 생산한다, LG 키보드를 생산한다, LG 마우스를 생산한다.
  5. Client : Abstract Factory, Abstract Products 사용

💻 코드

  1. Abstract Products

    public interface Monitor {
        void turnOn();
    }
    
    public interface Keyboard {
        void type();
    }
    
    public interface Mouse {
        void click();
    }
  2. Concrete Products

    // Monitor
    public class SamsungMonitor implements Monitor {
        @Override
        public void turnOn() {
            System.out.println("Samsung 모니터");
        }
    }
    
    public class LGMonitor implements Monitor {
        @Override
        public void turnOn() {
            System.out.println("LG 모니터");
        }
    }
    
    public class AppleMonitor implements Monitor {
        @Override
        public void turnOn() {
            System.out.println("Apple 모니터");
        }
    }
    
    // Keyboard
    public class SamsungKeyboard implements Keyboard {
        @Override
        public void type() {
            System.out.println("Samsung 키보드");
        }
    }
    
    public class LGKeyboard implements Keyboard {
        @Override
        public void type() {
            System.out.println("LG 키보드");
        }
    }
    
    public class AppleKeyboard implements Keyboard {
        @Override
        public void type() {
            System.out.println("Apple 키보드");
        }
    }
    
    // Mouse도 동일
  3. Abstract Factory

    public interface CompanyFactory {
        Monitor createMonitor();
    
        Keyboard createKeyboard();
    
        Mouse createMouse();
    }
  4. Concrete Factories

    public class SamsungFactory implements CompanyFactory {
        @Override
        public Monitor createMonitor() {
            return new SamsungMonitor();
        }
    
        @Override
        public Keyboard createKeyboard() {
            return new SamsungKeyboard();
        }
    
        @Override
        public Mouse createMouse() {
            return new SamsungMouse();
        }
    }
    
    public class LGFactory implements CompanyFactory {
        @Override
        public Monitor createMonitor() {
            return new LGMonitor();
        }
    
        @Override
        public Keyboard createKeyboard() {
            return new LGKeyboard();
        }
    
        @Override
        public Mouse createMouse() {
            return new LGMouse();
        }
    }
    
    public class AppleFactory implements CompanyFactory {
        @Override
        public Monitor createMonitor() {
            return new AppleMonitor();
        }
    
        @Override
        public Keyboard createKeyboard() {
            return new AppleKeyboard();
        }
    
        @Override
        public Mouse createMouse() {
            return new AppleMouse();
        }
    }
  5. Client

    public class Client {
        private static final CompanyFactory FACTORY = new Application().createFactory();
    
        public static void main(String[] args) {
            Monitor monitor = FACTORY.createMonitor();
            monitor.turnOn();
    
            Keyboard keyboard = FACTORY.createKeyboard();
            keyboard.type();
    
            Mouse mouse = FACTORY.createMouse();
            mouse.click();
        }
    }

    주의

    • Application이 환경 설정에 맞게 팩토리 타입을 고르고, 초기화 단계에서 concrete factory 객체를 생성해놓아야 한다.
  • Console

    // 입력
    APPLE
    
    // 출력
    Apple 모니터
    Apple 키보드
    Apple 마우스

🔮 장단점

  • 장점
    1. Open-Closed Principle: 집합에 새 제품이나 제품군을 추가할 때 핵심 코드를 변경할 필요가 없다.
    2. 클라이언트와 팩토리에서 생산되는 제품을 분리시킬 수 있다.
      • 클라이언트의 코드와 구체적인 제품의 결합성을 떨어트린다.
    3. 객체들의 집합을 생성해야 할 때 유용하다
      • 팩토리에서 얻어지는 제품들의 호환성을 확인할 수 있다.
  • 단점
    1. 많은 인터페이스와 클래스 -> 복잡한 코드

➰ 어떤 상황에서 사용될까?

  • Collectioniterator
    • Builder 패턴에서도 Iterator 구현하는데 사용된다고 한다. 뭐지 같이 쓰이는건가 조사 필요!

➕ Factory Method Pattern과의 차이점?

Factory Method

  • 조건에 따른 객체 생성을 Factory에게 위임한다.

Abstract Factory

  1. 연관이 있는 객체들끼리 묶어 Factory로 만든다.

  2. 조건에 따른 1.의 Factory 생성을 다시 Factory를 만들어 위임한다.

출처

좋은 웹페이지 즐겨찾기