ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 팩토리 패턴(Factory Pattern)
    CS이론/디자인패턴 2023. 8. 11. 17:10

    팩토리 패턴이란?

    팩토리 패턴(Factory Pattern)은 GoF의 생성 패턴 중 하나로 객체 생성 부분을 떼어내 추상화한 패턴입니다. 즉, 상속 관계의 클래스에서 상위 클래스는 뼈대를 정하고 하위 클래스는 객체 생성을 결정하는 패턴입니다. 팩토리 패턴은 팩토리 메서드 패턴(Factory Method Pattern)추상 팩토리 패턴(Abstract Factory Pattern) 두 가지가 있습니다.

    장점

    객체 생성 로직이 따로 떨어져 있기 때문에 결합도를 낮출 수 있으며, 유지 보수성이 증가됩니다. 팩토리 패턴은 새로운 Product 추가 시 기존의 코드는 수정하지 않고 새로운 Product만 생성하면 되기 때문에 확장에는 열려있고, 수정에는 닫혀있는 OCP(개방 폐쇄의 원칙)을 따릅니다.

    단점

    팩토리 패턴의 단점은 패턴을 구현할 많은 서브 클래스가 필요하기 때문에 코드가 복잡해질 수 있습니다.

    구현

    앞서 팩토리 패턴은 팩토리 메서드 패턴추상 팩토리 패턴 두 가지가 있다고 소개했습니다. 두 패턴을 알기 전에 심플 팩토리(Simple Factory)을 먼저 보고 가겠습니다.

     

    • 심플 팩토리(Simple Factory)

    심플 팩토리는 팩토리 메서드 패턴과 추상 팩토리 패턴의 베이스가 되는 가장 단순한 형태의 형식으로 엄밀히 따지면 디자인 패턴은 아니라 OOP에서 자주 쓰이는 관용구로 사용됩니다.

    interface Coffee {
        void makeCoffee();
        void drink();
    }
    
    class SimpleCoffeeFactory {
        public static Coffee orderCoffee(String type) {
            Coffee coffee = createCoffee(type);
            coffee.makeCoffee();
    
            return coffee;
        }
    
        private static Coffee createCoffee(String type) {
            switch(type) {
                case "Americano":
                    return new Americano();
                case "Latte":
                    return new Latte();
                default:
                    return new Maxim();
            }
        }
    }
    
    class Maxim implements Coffee {
        @Override
        public void makeCoffee() {
            System.out.println("Make Maxim Coffee");
        }
    
        @Override
        public void drink() {
            System.out.println("Drink Maxim Coffee");
        }
    }
    
    class Americano implements Coffee {
        @Override
        public void makeCoffee() {
            System.out.println("Make Americano Coffee");
        }
    
        @Override
        public void drink() {
            System.out.println("Drink Americano Coffee");
        }
    }
    
    class Latte implements Coffee {
        @Override
        public void makeCoffee() {
            System.out.println("Make Latte Coffee");
        }
    
        @Override
        public void drink() {
            System.out.println("Drink Latte Coffee");
        }
    }
    
    public class SimpleFactory {
        public static void main(String[] args) {
            Coffee coffee = SimpleCoffeeFactory.orderCoffee("Americano");
            coffee.drink();
    
            coffee = SimpleCoffeeFactory.orderCoffee("");
            coffee.drink();
        }
    }
    
    /* 출력 결과
    Make Americano Coffee
    Drink Americano Coffee
    Make Maxim Coffee
    Drink Maxim Coffee
    */

    코드를 살펴보면 클라이언트가 아닌 SimpleCoffeeFactory에서 createCoffee()를 통해 직접 객체를 생성합니다. 이처럼 심플 팩토리는 단순히 객체를 만드는 작업을 하나의 팩토리 클래스에 모아두는 것을 의미합니다.

     

    • 팩토리 메서드 패턴(Factory Method Pattern)

    심플 팩토리를 통해 각 클라이언트에서 구현 클래스에 의존하지 않도록 분리하는 작업을 했습니다. 하지만 새로운 클래스가 추가될 경우 Factory 클래스를 수정해야 한다는 한계가 있습니다. 하지만 기존 코드의 변경 없이 확장이 가능한 패턴이 팩토리 메서드 패턴입니다.

    interface Coffee {
        void createType();
        void makeAmericano();
        void makeLatte();
    }
    
    class PressCoffee implements Coffee {
        @Override
        public void createType() {
            System.out.println("Create Press Coffee");
        }
    
        @Override
        public void makeAmericano() {
            System.out.println("Make Americano at PressCoffee");
        }
    
        @Override
        public void makeLatte() {
            System.out.println("Make Latte at PressCoffee");
        }
    }
    
    abstract class CoffeeFactory {
        public Coffee newInstance() {
            Coffee coffee = createCoffee();
            coffee.createType();
    
            return coffee;
        }
    
        abstract Coffee createCoffee();
    }
    
    class PressCoffeeFactory extends CoffeeFactory {
        @Override
        Coffee createCoffee() {
            return new PressCoffee();
        }
    }
    
    public class FactoryMethodPattern {
        public static void main(String[] args) {
            CoffeeFactory coffeeFactory = new PressCoffeeFactory();
            Coffee coffee = coffeeFactory.newInstance();
            coffee.makeAmericano();
        }
    }
    
    /* 출력 결과
    Create Press Coffee
    Make Americano at PressCoffee
    */
    // 확장 - 새로운 클래스 추가할 경우
    interface Coffee {...}
    
    class PressCoffee implements Coffee {...}
    
    abstract class CoffeeFactory {...}
    
    class PressCoffeeFactory extends CoffeeFactory {...}
    
    class DripCoffee implements Coffee {
        @Override
        public void createType() {
            System.out.println("Create Drip Coffee");
        }
    
        @Override
        public void makeAmericano() {
            System.out.println("Make Americano at DripCoffee");
        }
    
        @Override
        public void makeLatte() {
            System.out.println("Make Latte at DripCoffee");
        }
    }
    
    class DripCoffeeFactory extends CoffeeFactory {
        @Override
        Coffee createCoffee() {
            return new DripCoffee();
        }
    }
    
    public class FactoryMethodPattern {
        public static void main(String[] args) {
            CoffeeFactory coffeeFactory = new PressCoffeeFactory();
            Coffee coffee = coffeeFactory.newInstance();
            coffee.makeAmericano();
    
            // 클라이언트 코드 수정없이 확장하여 사용
            CoffeeFactory dripFactory = new DripCoffeeFactory();
            Coffee dripCoffee = dripFactory.newInstance();
            dripCoffee.makeAmericano();
        }
    }
    
    /* 출력 결과
    Create Press Coffee
    Make Americano at PressCoffee
    Create Drip Coffee
    Make Americano at DripCoffee
    */

    이처럼 팩토리 메서드 패턴은 객체를 생성할 때 어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정하는 패턴입니다. 즉, 인스턴스 생성을 서브 클래스에게 위임합니다. 이 패턴의 장점은 확장할 때 기존 코드의 변경이 없어도 된다는 점이 있습니다. 즉, OCP원칙을 따르는 패턴입니다.

     

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

    추상 팩토리 패턴은 팩토리 메서드 패턴과 비슷해 보입니다. 하지만 추상 팩토리 패턴은 연관된 객체들을 모아둔다는 차이점이 있습니다. 즉, 구체적인 클래스에 의존하지 않고 서로 연관되거나 의존적인 객체들의 조합을 만드는 인터페이스를 제공하는 패턴입니다.

    interface Americano {}
    class DripAmericano implements Americano {}
    class PressAmericano implements Americano {}
    
    interface Latte {}
    class DripLatte implements Latte {}
    class PressLatte implements Latte {}
    
    interface CoffeeFactory {
        Americano createAmericano();
        Latte createLatte();
    }
    
    class DripCoffeeFactory implements CoffeeFactory {
        @Override
        public Americano createAmericano() {
            System.out.println("Create Americano at DripCoffee");
            return new DripAmericano();
        }
    
        @Override
        public Latte createLatte() {
            System.out.println("Create Latte at DripCoffee");
            return new DripLatte();
        }
    }
    
    class PressCoffeeFactory implements CoffeeFactory {
        @Override
        public Americano createAmericano() {
            System.out.println("Create Americano at PressCoffee");
            return new PressAmericano();
        }
    
        @Override
        public Latte createLatte() {
            System.out.println("Create Latte at PressCoffee");
            return new PressLatte();
        }
    }
    
    public class AbstractFactoryPattern {
        public static void main(String[] args) {
            use(new DripCoffeeFactory());
            use(new PressCoffeeFactory());
        }
    
        private static void use(CoffeeFactory coffeeFactory) {
            Americano americano = coffeeFactory.createAmericano();
            Latte latte = coffeeFactory.createLatte();
        }
    }
    
    /* 출력 결과
    Create Americano at DripCoffee
    Create Latte at DripCoffee
    Create Americano at PressCoffee
    Create Latte at PressCoffee
    */

    이처럼 Americano와 Latte라는 Product를 Coffee라는 하나의 공통점으로 묶어서 CoffeeFactory를 정의할 수 있었습니다. 팩토리 메서드 패턴과 비슷하지만 공통된 집합을 모아둔다는 특징이 있는데 추상 팩토리 패턴입니다.

     

    참고

    Factory 패턴 (1/3) - Simple Factory

     

    Factory 패턴 (1/3) - Simple Factory

    1. Overview Factory 패턴은 객체 생성 역할을 별도의 클래스 (Factory) 에게 위임하는 것이 가장 궁극적인 목표입니다. 디자인 패턴 중 Facotry 와 관련된 패턴은 크게 두 가지가 있습니다. 팩토리 메서드

    bcp0109.tistory.com

    [디자인 패턴] 팩토리 패턴 종류/개념/예제

     

    [디자인 패턴] 팩토리 패턴 종류/개념/예제

    이번 포스팅에서는 팩토리 패턴의 개념에 대해 포스팅하고자 한다. 1. 심플 팩토리 패턴 팩토리 패턴에는 팩토리 메소드 패턴, 추상 팩토리 패턴이있다. 이 두가지 패턴을 알기전에 먼저 심플 팩

    cjw-awdsd.tistory.com

    팩토리 패턴(Factory Pattern)

     

    팩토리 패턴(Factory Pattern)

    Factory Method Pattern이란? 팩토리 메소드 패턴에서는 객체를 생성하기 위한 인터페이스를 정의하는데, 어떤 클래스의 인스턴스를 만들지는 서브 클래스에서 결정하게 만드는 패턴이다. 왜 Factory Pat

    velog.io

    면접을 위한 CS 전공지식 노트 - 예스24

     

    면접을 위한 CS 전공지식 노트 - 예스24

    디자인 패턴, 네트워크, 운영체제, 데이터베이스, 자료 구조, 개발자 면접과 포트폴리오까지!CS 전공지식 습득과 면접 대비, 이 책 한 권이면 충분하다!개발자 면접에서 큰 비중을 차지하는 CS(Comp

    www.yes24.com

     

    'CS이론 > 디자인패턴' 카테고리의 다른 글

    싱글톤 패턴(Singleton Pattern)  (0) 2023.08.10

    댓글

Designed by Tistory.