본문 바로가기
카테고리 없음

[디자인 패턴] 팩토리 메소드

by 근즈리얼 2023. 8. 29.
728x90

팩토리 메소드 패턴

팩토리 메소드 패턴은 객체 생성을 공장 클래스로 캡슐화 처리하여 대신 생성하게 하는 디자인 패턴입니다.

 

다시 정리해보면,

클라이언트가 직접 new 연산자를 이용하여 객체를 생성하는 것이 아니라,

객체의 생성을 도맡아서 하는 팩토리 클래스를 만들고 이를 상속하는 서브 팩토리 클래스의 메소드에서 여러 가지 클래스를 만들어 내는 것입니다.

 

좀 더 이해를 쉽게 하기 위해서 그림을 그려왔습니다... ㅎㅎ 

 

순서대로 설명해 보겠습니다.

1. 추상 팩토리 클래스를 만듭니다.

2. 추상 팩토리 클래스를 상속한 서브 팩토리 클래스를 두 개 만듭니다.

3. 각각의 서브 팩토리 틀래스는 A상품과 B상품을 만들어냅니다.

4. A상품과 B상품은 각각 하나의 인터페이스를 상속받고 있고 추상 팩토리 클래스의 생성 메소드에서는 인터페이스를 return 하고 있습니다.

 

아래 그림을 보면 더 이해가 되실 거라고 생각합니다!!


밑에서 더 자세한 코드로 알아보겠습니다!

 

다만,

코드로 알아보기 전, 간단하게 팩토리 메소드가 어떤 형태를 갖고 있는지 이해했다면 장단점에 대해서 좀 더 명확하게 알아보도록 하겠습니다. (어디에 좋은지 알아야 더 재밌으니까요~!)

 

장점에는 무엇이 있을까요?

  • 생성자와 구현 객체의 강한 결합을 피할 수 있습니다.
  • 팩토리 메소드를 이용해서 객체의 생성 후 공통으로 할  일을 수행하도록 지정해줄 수 있습니다.
  • 캡슐화, 추상화를 통해 생성되는 객체의 구체적인 타입을 감출 수 있습니다.
  • 단일 책임 원칙을 지킬 수 있습니다. 
    • 객체 생성 코드를 한 곳으로 이동하여 코드를 유지 보수
  • 개방/폐쇄 원칙을 지킬 수 있습니다.
    • 기존 코드를 수정하지 않고 새로운 상품을 도입

 

단점은 무엇이 있을까요?

  • 각 상품이 생길 때마다 서브 팩토리 클래스가 증가하게 됩니다.
  • 코드의 복작성이 증가합니다.

추가적으로 그럼 언제 사용하면 좋을까요?

  • 클래스 생성과 사용의 로직을 분리하여 결합도를 낮출 때
  • 코드가 동작해야 하는 객체의 유형과 종속성을 캡슐화를 통해 정보 은닉 처리를 할 경우
  • 라이브러리나 프레임워크의 구성 요소를 확장할 때
  • 기존 객체를 재구성하기 보다 재사용하여 리소스를 절약하고자 할 때

이제는 정말로 좀 더 익숙한 예시를 통한 코드를 봐보겠습니다.

 

간단한 시나리오 설명을 하겠습니다.

1. 책 팩토리 메소드를 만듭니다.

2. 역사책 서브 팩토리 메소드와 과학책 서브 팩토리 메소드를 만듭니다.

3. 클라이언트는 각 서브 팩토리 메소드에서 역사책과 과학책을 만들어달라고 요청합니다.

 

Book과 Book를 상속받는 HistoryBook과 ScienceBook 코드입니다.

public class Book {

    String name;
    int page;
    String type;

    public Book(String name, int page) {
        this.name = name;
        this.page = page;
    }

    @Override
    public String toString() {
        return String.format("name : '%s', page : '%s', type : '%s'", name, page, type);
    }

}

public class HistoryBook extends Book{

    public HistoryBook(String name, int page) {
        super(name, page);
        this.type = "역사";
    }
}

public class ScienceBook extends Book{

    public ScienceBook(String name, int page) {
        super(name, page);
        this.type = "과학";
    }
}

가장 최상위 book 팩토리 메소드 클래스입니다.

import factorymethod.book.Book;

public abstract class BookFactory {

    public Book orderBook() {

        Book book = createBook();
        complete();

        return book;
    }

    abstract public Book createBook();

    private void complete() {
        System.out.println("다 만들었다!");
    }
}

각각 BookFactory를 상속 받은 서브 팩토리 클래스입니다.

싱글톤 객체를 만들어서 사용했습니다.

import factorymethod.book.Book;
import factorymethod.book.HistoryBook;

public class HistoryBookFactory extends BookFactory{

    private static class SingleInstanceHolder {
        private static final HistoryBookFactory INSTANCE = new HistoryBookFactory();
    }

    public static HistoryBookFactory getInstance() {
        return SingleInstanceHolder.INSTANCE;
    }

    @Override
    public Book createBook() {
        System.out.println("역사책 만드는 중~");
        return new HistoryBook("역사책", 100);
    }
}

import factorymethod.book.Book;
import factorymethod.book.ScienceBook;

public class ScienceBookFactory extends BookFactory{

    public static class SingleInstanceHolder {
        private static final ScienceBookFactory INSTANCE = new ScienceBookFactory();
    }

    public static ScienceBookFactory getInstance() {
        return SingleInstanceHolder.INSTANCE;
    }

    @Override
    public Book createBook() {
        System.out.println("과학책 만드는 중~");
        return new ScienceBook("과학책", 100);
    }
}

클라이언트 코드로 확인할 수 있습니다.

import factorymethod.book.Book;
import factorymethod.factory.HistoryBookFactory;
import factorymethod.factory.ScienceBookFactory;

public class Client {

    public static void main(String[] args) {

        Book historybook = HistoryBookFactory.getInstance().orderBook();
        System.out.println(historybook);

        Book scienceBook = ScienceBookFactory.getInstance().orderBook();
        System.out.println(scienceBook);
    }

}



/*
출력 결과 입니다~!~
역사책 만드는 중~
다 만들었다!
name : '역사책', page : '100', type : '역사'
과학책 만드는 중~
다 만들었다!
name : '과학책', page : '100', type : '과학'
*/

출력값을 증거로~

클라이언트는 각각의 서브 팩토리에 메소드를 이용해서 book을 생성한 것을 확인할 수 있습니다~!!

 

참고 자료
 

💠 팩토리 메서드(Factory Method) 패턴 - 완벽 마스터하기

Factory Method Pattern 팩토리 메소드 패턴은 객체 생성을 공장(Factory) 클래스로 캡슐화 처리하여 대신 생성하게 하는 생성 디자인 패턴이다. 즉, 클라이언트에서 직접 new 연산자를 통해 제품 객체를

inpa.tistory.com

  • 면접을 위한 cs 전공지식 노트
728x90

댓글