전 글의 심플 팩토리, 팩토리 메소드와 이번 글의 추상 팩토리를 모두 합쳐 구현한 예제 소스
AbstractFactory.cpp
추상 팩토리 패턴이란 공통 기능을 가지되, 약간식 다른 성격을 가지는 다양한 팩토리 인스턴스를 만든 후에 그 팩토리 인스턴스들을 사용하여 객체를 생성하는 방식이다.
팩토리 메소드 패턴은 클래스가 객체를 생성하는 패턴이라 하면, 추상 팩토리 패턴은 객체가 객체를 만드는 방식이다.
말이 좀 어려운대.. 소스 예제로 한번 보자.
class Dough
{
protected:
char dough[256];
public:
virtual ~Dough() {};
inline char* getChar() { return dough; }
};
class ThinCrustDough : public Dough
{
public:
ThinCrustDough() { strcpy_s( dough, "얇은 크러스트 " ); }
};
class ThickCrustDough : public Dough
{
public:
ThickCrustDough() { strcpy_s( dough, "두꺼운 크러스트 " ); }
};
class Sauce
{
protected:
char sauce[256];
public:
virtual ~Sauce() {};
inline char* getChar() { return sauce; }
};
class MarinaraSauce : public Sauce
{
public:
MarinaraSauce() { strcpy_s( sauce, "마리나라 " ); }
};
class TomatoSauce : public Sauce
{
public:
TomatoSauce() { strcpy_s( sauce, "토마토 " ); }
};
class HotSauce : public Sauce
{
public:
HotSauce() { strcpy_s( sauce, "핫 " ); }
};
class IPizzaIngredientFactory /// ingredient : 재료
{
public:
virtual ~IPizzaIngredientFactory() {};
virtual Dough* createDough() = 0;
virtual Sauce* createSauce() = 0;
};
class ChicagoPizzaIngredientFactory : public IPizzaIngredientFactory
{
public:
Dough* createDough() override
{
return new ThickCrustDough();
};
Sauce* createSauce() override
{
return new MarinaraSauce();
}
};
class NYPizzaIngredientFactory : public IPizzaIngredientFactory
{
public:
Dough* createDough() override
{
return new ThinCrustDough();
};
Sauce* createSauce() override
{
return new HotSauce();
}
};
ThinCrustDough, ThickCrustDough 클래스는 Dough를 상속 받고,
MarinaraSause, TomatoSause, HotSause 클래스는 Sause를 상속받아서 공통되게 한다.
IPizzaIngredientFactory에는 가상함수로 구성된 인터페이스 이다.
ChicagoPizzaIngredientFactory, NYPizzaIngredientFactory 클래스는 IPizzaIngredientFactory 인터페이스를 상속받아서 각각 createDough, createSause 메소드를 오버라이딩 하여 재정의 한다.
이렇게 되면 피자를 만든다는 것은 동일하지만 시카고 피자를 만들때 다뤄지는 재료들, 뉴욕 피자를 만들때 다줘지는 재료들을 조금씩 서로 달리 정의할수 있다는 것이다.
즉 각 팩토리마다 성격을 달리 구현 할수 있기 때문에 더 유연해 진다는 것이다.
*추상 팩토리 패턴은
생성하려고 하는 객체가 여러가지 형태는 비슷하지만 다른 팩토리 패턴으로 생성해야 할 경우,
객체들의 생성에 대한 구현이 아닌 인터페이스만을 노출시키고 싶을 때,
객체들 중에서 특정 객체를 선택해서 생성하고 싶을 때,
관련된 제품들이 함께 사용하도록 설계해서 이 부분에 대한 규약이 다른 외부에서 사용될 때도 지켜지게 하고 싶을 때 사용하면 유용하다.