티스토리 뷰

JAVA/디자인 패턴

Factory Method 패턴

kkoon9 2022. 3. 11. 00:46

템플릿 메서드에서는 상위 클래스에서 처리의 골격을 만들고, 하위 클래스에서 구체적인 처리의 내용을 만들었다.

템플릿 메서드 패턴을 인스턴스 생성의 장면에 적용한 것이 팩토리 메서드 패턴이다.

팩토리 메서드 패턴이란

factory는 ‘공장'이라는 의미다.

인스턴스를 생성하는 공장을 템플릿 메서드 패턴으로 구성한 것이 팩토리 메서드 패턴이 된다.

팩토리 메서드 패턴에서는 인스턴스를 만드는 방법을 상위 클래스 측에서 결정하지만 구체적인 클래스 이름까지는 결정하지 않는다.

따라서 인스턴스 생성을 위한 골격(framework)과 실제의 인스턴스 생성의 클래스를 분리해서 생각할 수 있다.

신분증명서 카드(ID 카드)를 만드는 예제 코드

  • Product 추상 클래스 : (framework 패키지 내 존재) use() 추상 메서드 정의
  • Factory 추상 클래스 : (framework 패키지 내 존재) create() 메서드를 구현
  • IDCard 클래스 : (idcard 패키지 내 존재) use() 구현
  • IDCardFactory 클래스 : (idcard 패키지 내 존재) createProduct(), registerProduct() 구현
  • Main 클래스

Product 클래스

framework 패키지 내에 존재한다.

제품을 표현하고 이 클래스에서는 추상 메서드 use()만이 선언되어 있다.

Factory 클래스

framework 패키지 내에 존재한다.

템플릿 메서드 패턴이 사용되고 있다.

  • createProduct() : 제품을 만드는 역할
  • registerProduct() : 제품을 등록하는 역할

구현은 하위 클래스에서 진행된다.

 

framework에서 공장이란 ‘create 메서드에서 Product의 인스턴스를 생성하는 것'으로 규정한다.

create 메서드는 ‘createProduct에서 제품을 만들어서 registerProduct에서 등록한다'라는 순서로 구현된다.

 

다시 한 번 강조하지만 팩토리 메서드 패턴에서는 인스턴스를 생성할 때 템플릿 메서드 패턴을 사용한다.

IDCard 클래스

idcard 패키지 내에 존재한다.

Product 클래스의 하위 클래스로 정의한다.

IDCardFactory 클래스

idcard 패키지 내에 존재한다.

Factory 클래스의 하위 클래스로 정의한다.

  • createProduct() : IDCard의 인스턴스를 생성해서 제품을 만드는 역할
  • registerProduct() : IDCard의 onwer를 owners 필드에 추가해서 등록하는 역할

Main 클래스

framework 패키지와 idcard 패키지를 이용해서 다음과 같은 실행 코드를 작성할 수 있다.

package factory_method;

import factory_method.framework.Factory;
import factory_method.framework.Product;
import factory_method.idcard.IDCardFactory;

public class Main {
    public static void main(String[] args) {
        Factory factory = new IDCardFactory();
        Product card1 = factory.create("홍길동");
        Product card2 = factory.create("이순신");
        Product card3 = factory.create("강감찬");
        card1.use();
        card2.use();
        card3.use();

    }
}

 

Factory Method 패턴의 핵심 키워드

예제 코드와 동작을 살펴봤으니 이젠 핵심 키워드를 살펴보자.

Product(제품)의 역할 - Product

framework 쪽에 포함되어 있다.

이 패턴에서 생성되는 인스턴스가 가져야 할 인터페이스(API)를 결정하는 것은 추상 클래스다.

구체적인 내용은 ConcreteProduct 역할이 가져간다.

Creator(작성자)의 역할 - Factory

framework 쪽에 포함되어 있다.

실제로 생성하는 ConcreteProduct 역할에 가지고 있는 정보가 없다.

Creator 역할이 가지고있는 정보는 Product 역할과 인스턴스 생성의 메서드를 호출하면 Product가 생성된다는 것뿐이다.

new를 사용해서 실제의 인스턴스를 생성하는 대신에, 인스턴스 생성을 위한 메서드를 호출해서 구체적인 클래스 이름에 의한 속박에서 상위 클래스를 자유롭게 만든다.

ConcreteProduct(구체적인 제품)의 역할 - IDCard

idcard 쪽에 포함되어 있다.

구체적인 제품을 결정하는 역할을 한다.

ConcreteCreator(구체적인 작성자)의 역할 - IDCardFactory

idcard 쪽에 포함되어 있다.

구체적인 제품을 만드는 클래스를 결정하는 역할을 한다.

 

🤔 추상적인 골격과 구체적인 내용이라.. 이걸 둘로 나눈 이유가 뭘까?

 

위 예제에서 추상적인 골격은 framework 패키지, 구체적인 내용은 idcard 패키지로 나누었다.

여기에서 동일한 framework를 사용해서 전혀 다른 ‘제품'과 ‘공장'을 만든다고 생각해보자.

예를 들어 TV와 TV공장을 만든다고 해보자.

이런 경우 framework 패키지를 import한 별도의 television 패키지를 만들게 된다.

여기에서는 framework 패키지의 내용을 수정하지 않아도 전혀 다른 제품과 공장을 만들 수 있다.

이것을 framework 패키지는 idcard나 television 패키지에 의존하지 않다라고 표현한다.

인스턴스 생성 - 메서드의 구현 방법

위 예제의 createProduct 메서드의 기술 방법은 다음과 같이 세 가지가 있다.

[1]. 추상 메서드로 한다.

추상 메서드로 하면 하위 클래스는 반드시 이 메서드를 구현해야 한다.

구현되어 있지 않으면 컴파일 에러가 발생한다.

[2]. 디폴트의 구현을 준비해 둔다.

디폴트의 구현을 준비해 두고 하위 클래스에서 구현하지 않았을 때 사용하면 된다.

class Factory {
    public Product createProduct(String name) {
        return new Product(name);
    }
}

단, 이 경우에는 Product 클래스에 대해서 직접 new를 이용하므로 Product 클래스를 추상 클래스로 둘 수 없다.

[3]. 에러를 이용한다.

디폴트 구현 내용을 에러로 처리해 두면, 하위 클래스에서 구현하지 않았을 경우에는 실행할 때 에러가 발생한다.

class Factory {
    public Product createProduct(String name) {
        throw new FactoryMethodRuntimeException();
    }
}

단, 위 코드에서 있는 FactoryMethodRuntimeException을 별도로 작성해야 한다.

패턴 이용과 개발자 간의 의사 소통(주석과 개발 문서 이용)

실제로 이루어지는 조작에 비해서는 복잡함이 느껴진다.

이것은 1개의 클래스를 읽는 것만으로는 동작을 잘 이해할 수 없기 때문이다.

상위 클래스에서 동작의 골격을 이해하고 거기에서 사용되고 있는 추상 메서드가 무엇인지를 확인하고, 또한 그 추상 메서드를 실제로 구현하고 있는 클래스의 소스 코드를 살펴볼 필요가 있다.

일반적으로 디자인 패턴을 사용해서 어떤 클래스를 설계할 때, 그 클래스를 보수하는 사람에게 설계자가 의도한 디자인 패턴이 무엇인지를 전달할 필요가 있다.

프로그램의 주석이나 개발 문서 안에 실제로 사용되고 있는 디자인 패턴의 명칭과 의도를 기술해 놓는 것도 좋은 방법이다.

관련 패턴

  • Template Method 패턴
  • Singleton 패턴
  • Composite 패턴
  • Iterator 패턴

'JAVA > 디자인 패턴' 카테고리의 다른 글

프로토타입 패턴  (0) 2022.03.15
싱글톤(Singleton) 패턴  (0) 2022.03.11
Template Method 패턴  (0) 2022.03.10
어댑터 패턴  (0) 2022.03.09
Iterator 패턴  (0) 2022.03.08
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함