ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java Design Pattern - 추상 팩토리 패턴(Abstract Factory Pattern)
    Language/Java Design Pattern 2022. 11. 22. 14:31

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

    추상 팩토리 패턴이란?

    추상 팩토리 패턴이라는 이름만 봐서는 팩토리 메서드 패턴과 비슷해 보이지만, 명확한 차이점이 있다.

     

    1. 팩토리 메서드 패턴 : 조건에 따른 객체 생성을 팩토리 클래스로 위임하여, 팩토리 클래스에서 객체를 생성하는 패턴

    2. 추상 팩토리 패턴 : 서로 관련이 있는 객체들을 통째로 묶어서 팩토리 클래스로 만들고, 이들 팩토리를 조건에 따라 생성하도록 다시 팩토리를 만들어서 객체를 생성하는 패턴

     

    추상 팩토리 패턴은 어떻게 보면, 팩토리 메서드 패턴을 좀 더 캡슐화한 방식이라고 할 수 있다.

     

    예를 들어, 컴퓨터를 생산하는 공장이 있을 때 마우스, 키보드, 모니터의 제조사로 Samsung과 LG가 있다고 가정해 보겠다.

    컴퓨터는 같은 제조사인 구성품들로 생성되어야 한다. 다시 말해, SamsungComputer 객체는 항상 삼성 마우스, 키보드, 모니터 객체들이 묶여서 생산되어야 한다.

    즉, 객체를 일관적으로 생산해야 할 필요가 있다.

     

    또한, 코드 레벨에서 보면, SamsungComputer인지 LGComputer인지는 조건에 따라 분기될 것이기 때문에 팩토리 메서드 패턴과 같이 조건에 따라 객체를 생성하는 부분을 Factory 클래스로 정의해야 한다.

     

    주의해야 할 점은 추상 팩토리 패턴은 팩토리 메서드 패턴의 상위 호환이 아니라는 점이다.

    두 패턴의 차이는 명확하기 때문에 상황에 따라 적절한 선택을 해야 한다.

     

    추상 팩토리 패턴의 사용 이유

     

    팩토리 메서드 패턴을 사용하여, 컴퓨터를 생산하는 로직을 구현해보도록 하겠다.

     

    public class LGKeyboard implements Keyboard {
        public LGKeyboard(){
            System.out.println("LG 키보드 생성");
        }
    }
    public class SamsungKeyboard implements Keyboard {
        public SamsungKeyboard(){
            System.out.println("Samsung 키보드 생성");
        }
    }
    public interface Keyboard {
    }
    public class KeyboardFactory {
        public Keyboard createKeyboard(String type){
            Keyboard keyboard = null;
            switch (type){
                case "LG":
                    keyboard = new LGKeyboard();
                    break;
                case "Samsung":
                    keyboard = new SamsungKeyboard();
                    break;
            }
            return keyboard;
        }
    }

     

    우선, 키보드 관련 클래스들을 정의하겠다. LGKeyboard와 SamsungKeyboard 클래스를 정의하고, 이를 캡슐화하는 Keyboard 인터페이스를 정의한다.

    그리고 KeyboardFactory 클래스에서 입력 값에 따라 LGKeyboard 객체를 생성할지, SamsungKeyboard를 생성할지 결정한다.

     

    public class LGMouse implements Mouse {
        public LGMouse() {
            System.out.println("LG 마우스 생성");
        }
    }
    public class SamsungMouse implements Mouse {
        public SamsungMouse() {
            System.out.println("Samsung 마우스 생성");
        }
    }
    public interface Mouse {
    }
    public class MouseFactory {
        public Mouse createMouse(String type) {
            Mouse mouse = null;
            switch (type) {
                case "LG":
                    mouse = new LGMouse();
                    break;
                case "Samsung":
                    mouse = new SamsungMouse();
                    break;
            }
            return mouse;
        }
    }

    Keyboard와 동일하게 Mouse 관련 클래스들을 정의한다.

     

    public class ComputerFactory {
        public void createComputer(String type) {
            KeyboardFactory keyboardFactory = new KeyboardFactory();
            MouseFactory mouseFactory = new MouseFactory();
    
            Keyboard keyboard = keyboardFactory.createKeyboard(type);
            Mouse mouse = mouseFactory.createMouse(type);
    
            System.out.println(type + " 컴퓨터 완성");
        }
    }

    다음으로 ComputerFactory 클래스를 구현한다. ComputerFactory 클래스는 KeyboardFactory와 MouseFactory 객체를 생성해서 어떤 제조사의 키보드와 마우스를 생산할 것인지 결정한다.

     

    public class Client {
        public static void main(String[] args) {
            ComputerFactory factory = new ComputerFactory();
            factory.createComputer("LG");
        }
    }

    마지막으로, 컴퓨터를 생산하기 위한 Client 클래스를 구현한다.

     

    팩토리 메서드 패턴을 사용하여, 컴퓨터를 생산해보았다.

    그런데, 컴퓨터의 구성품은 키보드, 마우스뿐만 아니라 본체 구성품들, 모니터, 스피커, 프린터 등 여러 가지가 있다.

     

    public class ComputerFactory {
        public void createComputer(String type) {
            KeyboardFactory keyboardFactory = new KeyboardFactory();
            MouseFactory mouseFactory = new MouseFactory();
            BodyFactory bodyFactory = new BodyFactory();
            MonitorFactory monitorFactory = new MonitorFactory();
            SpeakerFactory speakerFactory = new SpeakerFactory();
            PrinterFactory printerFactory = new PrinterFactory();
    
            keyboardFactory.createKeyboard(type);
            mouseFactory.createMouse(type);
            bodyFactory.createBody(type);
            monitorFactory.createMonitor(type);
            speakerFactory.createSpeaker(type);
            printerFactory.createPrinter(type);
            System.out.println(type + " 컴퓨터 완성");
        }
    }

    위 코드를 그대로 사용하고자 한다면, 본체 팩토리, 모니터 팩토리, 스피커 팩토리 클래스 등을 정의해야 하고, ComputerFactory 클래스에서는 위 코드와 같이 각 팩토리 클래스 객체들을 생성해서 컴퓨터를 완성시켜야 할 것이다.

     

    각각의 컴퓨터 구성품들을 Samsung이냐 LG냐 구분할 필요 없이, Samsung 컴퓨터를 만들고자 한다면 구성품이 모두 Samsung이 되도록 일관된 방식으로 객체를 생성할 필요가 있다.

     

    따라서, 추상 팩토리 패턴을 적용하여 구성품이 모두 동일한 제조사가 되도록 개선해보겠다.

     

    추상 팩토리 패턴의 적용

     

    패턴 적용 전과 비교했을 때의 차이점은 아래와 같다.

     

    1. 어떤 제조사의 부품을 선택할지 결정하는 팩토리 클래스(KeyboardFactory, MouseFactory)가 제거되고, ComputerFactory 클래스(LGComputerFactory, SamsungComputerFactory)가 추가되었다.

    2. LGComputerFactory, SamsungComputerFactory 클래스는 ComputerFactory 인터페이스로 캡슐화하고, 어떤 제조사의 부품을 생성할 것인지 명확하기 때문에, 각각의 제조사의 부품을 생성한다.

    3. FactoryOfComputerFactory 클래스에서 컴퓨터를 생산하는 createComputer() 메서드를 호출한다.

     

    public class SamsungComputerFactory implements ComputerFactory {
        @Override
        public Keyboard createKeyboard() {
            return new SamsungKeyboard();
        }
    
        @Override
        public Mouse createMouse() {
            return new SamsungMouse();
        }
    }
    public class LGComputerFactory implements ComputerFactory {
        @Override
        public Keyboard createKeyboard() {
            return new LGKeyboard();
        }
    
        @Override
        public Mouse createMouse() {
            return new LGMouse();
        }
    }
    public interface ComputerFactory {
        public Keyboard createKeyboard();
        public Mouse createMouse();
    }

    우선, SamsungComputerFactory, LGComputerFactory 클래스를 정의하고, 이들을 캡슐화하는 ComputerFactory 인터페이스를 정의한다.

    각 클래스는 자신의 제조사 부품 객체를 생성한다. 예를 들어, SamsungComputerFactory 클래스는 삼성 키보드, 삼성 마우스를 가지므로 SamsungKeyboard, SamsungMouse 객체를 생성한다.

     

    public class FactoryOfComputerFactory {
        public void createComputer(String type) {
            ComputerFactory factory = null;
            switch (type) {
                case "Samsung":
                    factory = new SamsungComputerFactory();
                    break;
                case "LG":
                    factory = new LGComputerFactory();
                    break;
            }
    
            factory.createKeyboard();
            factory.createMouse();
            System.out.println(type + " 컴퓨터 완성");
        }
    }

    다음으로, FactoryOfComputerFactory 클래스를 정의한다. 이 클래스는 패턴 적용 전 ComputerFactory 클래스와 하는 일이 동일하다.

    입력값에 따라 객체 생성을 분기하는데, 이때 어떤 제조사 컴퓨터 객체를 생성할지 결정한다. 부품이 아니라 컴퓨터 객체를 생성한다는 점에서 이전 코드와 차이점이 있다.

     

    public class Client {
        public static void main(String[] args) {
            FactoryOfComputerFactory factory = new FactoryOfComputerFactory();
            factory.createComputer("LG");
        }
    }

    마지막으로, 컴퓨터를 생산하기 위한 Client 클래스를 정의한다. 결과는 이전과 동일하다.

     

    이상으로, 추상 팩토리 패턴에 대해서 알아보았다.

    정리하자면, 패턴 적용 전(팩토리 메서드 패턴)에는 구성품마다 팩토리를 만들어서 어떠한 객체를 생성했다. 반면에, 추상 팩토리 패턴에서는 관련된 객체들을 한꺼번에 캡슐화하여 팩토리를 만든 후 일관되게 객체를 생성하도록 하였다.


    출처

    https://victorydntmd.tistory.com/300

     

    728x90

    댓글

Designed by Tistory.