팩토리 메서드 패턴(Factory Method Pattern)#
- 팩토리 메서드 패턴은 두 가지 패턴(팩토리 패턴, 템플릿 메서드 패턴)이 결합한 팩토리 확장 패턴입니다.
- 추상화(Abstract)는 팩토리 메서드 패턴을 구현하는데 중요한 개념입니다.
- 객체를 생성하는 팩토리와 객체의 대상이 되는 클래스를 각각 추상화합니다.
팩토리 메서드 패턴의 구조#
- 인터페이스 클래스(Interface Class)는 클래스의 정의만 존재하는 클래스입니다.
- 클래스의 실제 구현은 인터페이스 클래스를 상속하는 세부 클래스에서 구현합니다.
- 팩토리 메서드는 팩토리와 생성 클래스를 인터페이스로 구현합니다.
팩토리 메서드 패턴: 인터페이스 클래스#
- 팩토리 메서드 패턴의 인터페이스 클래스를 선언합니다.
- 생성된 객체를 반환하는
create()
메서드를 작성합니다. - 구체적인 객체의 생성은
IFactory
를 상속하는 다양한 구현 클래스에 위임합니다. create()
메서드는 자식 클래스에서 오버라이딩을 하지 못하게 final
키워드를 추가합니다.- 오버라이딩(Overriding): 부모 클래스의 메서드를 자식 클래스가 재정의하는 것을 의미합니다.
- 또한 자식 클래스에서만 사용이 가능하도록
protected
접근 제한자로 한정합니다. - 실제 구체적인 객체를 생성하기 위한
IProduct
인터페이스 클래스를 반환합니다.
class IFactory
{
public:
virtual std::shared_ptr<IProduct> create() final
{
return this->createProduct();
}
protected:
virtual std::shared_ptr<IProduct> createProduct() = 0;
};
팩토리 메서드 패턴: 구현#
- 팩토리 메서드 인터페이스 클래스
IFactory
를 상속받는 구체적인 구현 클래스를 작성합니다. - 예제로 LG와 Apple 노트북을 만드는 자식 클래스를 구현합니다.
// 객체의 생성을 담당할 자식 클래스의 실제 구현
class LGFactory final :
public IFactory
{
protected:
std::shared_ptr<IProduct> createProduct() override
{
return std::make_shared<LGProduct>();
}
};
// 객체의 생성을 담당할 자식 클래스의 실제 구현
class AppleFactory final :
public IFactory
{
protected:
std::shared_ptr<IProduct> createProduct() override
{
return std::make_shared<AppleProduct>();
}
};
팩토리 메서드 패턴: 생성할 객체의 인터페이스 클래스#
// 생성할 객체의 인터페이스 클래스
class IProduct
{
public:
virtual void name() = 0;
};
팩토리 메서드 패턴: 생성할 객체의 구현#
IProduct
를 상속하는 자식 클래스를 구현합니다.
// 실제 생성할 객체 클래스
class LGProduct final :
public IProduct
{
public:
void name() override
{
std::cout << "LG Gram laptop" << std::endl;
}
};
// 실제 생성할 객체 클래스
class AppleProduct final :
public IProduct
{
public:
void name() override
{
std::cout << "Apple Macbook laptop" << std::endl;
}
};
팩토리 메서드 패턴: 실행 코드#
- 팩토리 메서드 인터페이스 클래스로 팩토리 메서드 객체를 생성하지만, 생성할 객체를 반환하는 구체적인 팩토리 메서드 타입을 지정합니다.
- 팩토리 메서드 인터페이스 클래스의 메서드는
IProduct
를 반환하지만, 이를 호출하는 쪽에서 구체적인 클래스를 명시할 경우, 해당 클래스를 생성하여 반환합니다.
int main(const int argc, const char* argv[])
{
std::shared_ptr<IFactory> factory = std::make_shared<AppleFactory>();
std::shared_ptr<IProduct> apple = factory->create();
apple->name();
factory.reset(new LGFactory);
std::shared_ptr<IProduct> lg = factory->create();
lg->name();
return 0;
}
팩토리 메서드의 템플릿 적용#
- 지금까지의 구조는 생성할 객체의 대상이 많아지면,
IProduct
를 상속하는 클래스를 만들어야 합니다. - 이렇게 되면 클래스의 갯수가 늘어나고, 관리해야 하는 클래스가 많아지는 단점이 있습니다.
IProduct
를 상속하여 특별한 추가 메서드를 작성하는 경우가 아니라면, C++
의 template
을 사용하여 범용적인 객체 생성 클래스를 작성할수 있습니다.
template<typename SProduct>
class SFactory final :
public IFactory
{
protected:
std::shared_ptr<SProduct> createProduct() override
{
return std::make_shared<SProduct>();
}
};
- 이러한 방법을 사용하면 템플릿에 지정되는
SProduct
에 따라 코드를 자동으로 생성할수 있습니다.