팩토리 패턴(Factory Pattern)
- 팩토리 패턴은 생성 패턴 중에서도 가장 기본이 되는 패턴입니다.
C++
에서는 클래스의 인스턴스를 생성하기 위해서new
키워드를 사용합니다.C++11
이상의 모던 C++(Mordern C++
)에서는 객체의 생성으로new
키워드를 사용하는 것을 추천하지 않습니다.shared_ptr
이나unique_ptr
과 같은 스마트 포인터(Smart Pointer)를 사용하길 권고합니다.
- 일반적인 객체를 생성하는 방법은 다음과 같습니다.
|
|
- 이렇게 객체를 생성하는 키워드
new
나 C++ STL 스마트 포인터(std::make_shared<T>
)를 사용하여 객체를 직접 생성하면 객체의 의존성이 발생하는 문제가 있습니다. (결합 관계가 발생하였다고도 합니다.) - 강력한 결합 관계가 되면 클래스 이름의 수정과 같이 변경사항이 발생할 경우 모든 코드를 찾아 수정해야 합니다.
- 팩토리 패턴은 이러한 결합 관계를 최소화하려는 목적이 있으며, 객체의 생성을 간접적으로 수행합니다.
팩토리 패턴의 의미
- 팩토리 패턴은 객체 생성을 별도의 클래스로 분리하여 생성을 위임합니다.
- 즉 객체를 생성하고 캡슐화하여 위임하는 것을 의미합니다.
팩토리 패턴: 생성할 객체의 인터페이스 클래스 선언
- C++에는 가상 함수(Virtual Function)를 사용하면 많은 이점이 있습니다.
- 팩토리 패턴에도 가상 함수를 사용합니다.
|
|
- 팩토리로 생성할 객체들의 타입을 구분할
Language
가 필요합니다. - 객체의 타입을 구분하지 않더라도, 공통된 인터페이스를 갖는 인터페이스 클래스
ILanguage
가 필요합니다.
팩토리 패턴: 객체 생성 클래스 구현
- 객체 생성의 역할을 수행할 클래스를 하나 만듭니다.
|
|
- 객체를 생성할 팩토리는 반드시 생성할 객체의 타입을 알아야 합니다.
- 객체의 타입을 모른다면 어떤 객체를 만들어야 할지 모르기 때문입니다.
팩토리 패턴: 실제 임무를 수행할 객체 클래스 구현
- 인터페이스 클래스를 상속받아, 실제로 사용할 클래스를 구현합니다.
C++
문법적으로 상속(Inheritance)이지만 관용적 표현으로인터페이스를 구현한다.
라는 표현을 사용합니다.- 인터페이스 클래스는 추상화된 클래스로 구현체가 없기 때문입니다.
- 실제로 인터페이스 클래스를 상속하는 자식 클래스가 해당 인터페이스를 실제로 구현하기 때문입니다.
|
|
English
클래스와Korean
클래스는 모두ILanguage
인터페이스의text()
가상 함수를 오버로딩하여 구현하고 있습니다.
팩토리 패턴: 객체의 생성을 호출할 클래스 구현
- 팩토리를 사용하여 객체들을 생성할 클래스를 구현해봅니다.
|
|
- 한 가지 중요한 점은 팩토리 클래스의
getInstance()
의 반환 값은std::make_shared<Korean>()
또는std::make_shared<English>()
입니다. - 하지만 이들의 추상체인
ILanguage
클래스로도Korean
와English
를 받을 수 있으며, 이들의 공통 메서드인text()
를 호출할 수 있습니다. - 타입이
ILanguage
여도 실제로 반환한Korean
와English
클래스의text()
메서드가 실행됩니다.
팩토리 패턴: 실행 코드
|
|
이처럼 팩토리 패턴은 생성과 관련된 모든 처리를 별도의 클래스로 위임합니다.
팩토리 패턴의 장/단점은 다음과 같습니다.
장점
- 클래스의 유연성과 확장성이 개선된다.
- 어떤 객체를 생성할지 모르는 초반에 유용하다.
단점
- 생성을 전담할 클래스가 생기므로, 관리해야하는 클래스가 늘어난다.
- 팩토리가 실제로 생성할 객체들의 타입을 알아야 한다.
객체의 타입을 알아야 하는 팩토리 패턴의 단점은 객체의 타입까지도 추상화한 팩토리 메서드 패턴으로 발전하게 됩니다.
심플 팩토리(Simple Factory)
- 팩토리 패턴은 객체의 생성을 외부 클래스로 위임한다고 하였습니다.
- 심플 팩토리는 객체의 생성을 외부 클래스가 아닌 내부적으로 해결하는 방법입니다.
|
|
- 이처럼 객체의 생성이 내부 메서드로 이동하였습니다.
- 하지만 실제로 생성할 객체의 타입을 알아야 한다는 단점은 변함 없습니다.