디자인패턴

[GoF의 디자인 패턴] 팩토리 메서드

hee9 2020. 5. 10. 10:06

의도

  객체를 생성하기 위해서 인터페이스를 정의하고, 어떤 클래스의 인스턴스를 생성할지에 대한 결정은 서브클래스에서 내리도록 한다.

 

동기 (사용 예시)

  사용자에게 다양한 종류의 문서를 표현하는 응용프로그램 프레임워크가 있다고 가정했을때 다음 두 가지 추상화가 필요하다

  • Application 클래스

  • Document 클래스

    어떤 응용프로그램을 만드는지에 따라서 인스턴스로 만들어지는 Document의 서브 클래스가 달라지기 때문에 Application 클래스에서 어떤 Document의 인스턴스를 생성하는지 미리 예측할 수 없다.

    이러한 상황에서 이 패턴은 Document의 서브클래스 중 어느 것을 생성하는지에 정보를 캡슐화하고, 이를 Application 클래스와 분리한다.

    Application 클래스의 서브클래스는 추상화된 CreateDocument() 연산을 재정의해서 적당한 Document 클래스의 서브클래스를 반환하도록 한다.

참고할만한 예시

https://jdm.kr/blog/180

 

활용성

  팩토리 메서드 디자인 패턴을 사용하는 상황

  • 어떤 클래스가 자신이 생성해야 하는 객체의 클래스를 예측할 수 없을 때

  • 생성할 객체를 기술하는 책임을 자신의 서브클래스가 지정했으면 할 때

  • 객체 생성의 책임을 몇 개의 서브클래스 중 하나에 위임하고 어떤 서브클래스가 위임자인지에 대한 정보를 포괄적으로 관리하고 싶을 때 (반환받은 Document 클래스의 서브클래스를 사용하면 됌)

 

구조

  • Product(Document) : 팩토리 메서드가 생성하는 객체의 인터페이스 정의

  • ConcreateProduct(MyDocument) : Product 클래스(추상/인터페이스)를 실제로 구현한 내용

  • Creator(Application) : Product 타입의 객체를 반환하는 팩토리 메서드 정의, 위의 예시에서는 팩토리 메서드를 통해서 ConcreateProduct 객체를 반환한다.

  • ConcreateCreator(MyApplication) : 팩토리 메서드를 재정의하여 적당한 ConcreteProduct의 인스턴스 생성

    • 협력 방법

    Creator는 자신의 서브클래스를 통해서 실제 필요한 팩토리 메서드를 정의하고, 이를 통해서 상황에 맞는 적절한 ConcreteProduct의 인스턴스를 반환할 수 있게 한다.

 

결과

  팩토리 메서드 패턴을 적용함으로써 구상 클래스에 코드가 종속되지 않는다. 위의 예시에서 보면 Product 클래스에 정의된 인터페이스와 동작하기 때문에 서브클래스 ConcreateProduct가 추가되었을때 코드레벨에서 대응해야하는 양을 줄일 수 있다.

  • 클래스간의 결합도를 낮추기(클래스 변경점이 생겼을 때 다른 클래스에 영향도 최소화)

  • 직접 객체를 생성해 사용하는 것을 방지하고 서브클래스에 생성을 위임함으로써 의존성 제거, 확장에 용이

  • 인터페이스에(Product) 맞춰서 코딩을 함으로써 다형성으로 얻을 수 있는 장점 (여러 변화에 대처)

    다만 주의해야할 점은 팩토리 메서드는 새로운 concreateProduct를 추가하려고 할때마다 서브클래싱이 필요하다는 점이다. 불필요한 클래스 재정의 발생 가능성이 있다.

 

구현

  구현 시 고려해야하는 상황

  1. 구현 방법 정하기

    • Creator 클래스를 추상클래스로 정의하고 정의한 팩토리 메서드에 대한 구현은 제공 X

    • Creator를 구체 클래스로 정의하고 팩토리 메서드에 대한 기본 구현을 제공

    1. 팩토리 메서드 매개변수화

    팩토리 메서드가 매개변수를 받아서 어떤 종류의 Product를 생성할지 식별하게 할 수 있다.

    1. 언어별 구현 방법 상이

    2. 템플릿을 사용해서 서브클래싱

    팩토리 메서드를 사용함으로써 발생할 수 있는 단점은 Product 클래스를 추가하려고 할때마다 서브클래싱을 해야 한다는 점이다. Creator의 서브클래스가 되는 템플릿 클래스를 정의하고 이것이 Product 클래스로 매개변화되도록 구현한다.

    1. 명명 규칙의 중요성

    팩토리 메서드를 사용한다는 사실을 명확하게 할 수 있도록 Creator 클래스의 이름 등을 통일 (-Factory.java)