2015년 11월 17일 화요일

Abstract Factory Pattern (추상 팩토리 패턴)

Abstract Factory를 이해하기 전에 Factory Method를 먼저 알아보고, 차이점을 비교해보면 좋을 듯 싶다.
의도
  • 서로 관련성 있거나 독립적인 여러 객체의 집합을 생성할 수 있는 인터페이스 제공하는 패턴
이럴 때 사용하자.
  • 객체 생성을 클라이언트가 직접하는 것이 아니라, 간접적으로 수행함으로써 클라이언트가 객체의 생성이나 구성 또는 표현 방식을 독립적이도록 만들고자 할 때
  • 여러 제품군 중 사용 제품군을 쉽게 선택할 수 있도록 만들고 싶을 때
  • 서로 관련된 제품들이 하나의 제품군을 형성하고, 이런 제품군이 여러 개 존재하는 상황에서 생성되는 제품 객체가 항상 같은 제품군에 속하는 것을 확실히 보장하고 싶을 때
  • 제품들에 대한 클래스 라이브러리를 만들어야 하는데 그 인터페이스만 드러내고 구현은 숨기고 싶을 때
장점은?
  • 객체가 생성되는 방식이나 과정 및 책임을 클라이언터가 몰라도 된다.
  • 제품군간 교제가 쉽다.
  • 제품군들이 실수로 섞여서 사용되는 것이 자연스럽게 방지된다.
단점은?
  • 제품군의 개수가 늘어날수록 Concrete Factory 클래스의 개수도 늘어난다.
  • 제품군에 새로운 제품이 추가되어야 할 경우 모든 Factory 클래스를 수정해야 한다.
코드
CProduct 클래스 (제품군 추상 클래스)
class CProduct
{
public:
   CProduct() {};
   virtual ~CProduct() {};
   virtual string ToString() = 0;
};

CPhone, CCar 클래스 (제품군 Concrete 클래스)
class CPhone : public CProduct
{
public:
   CPhone(string strName, int nPrice) { m_strName = strName; m_nPrice = nPrice; };
   virtual ~CPhone() {};

   virtual string ToString() {
      ostringstream sout;
      sout << "Name: " << m_strName << ", Price: $" << m_nPrice;
      return sout.str();
   }
private:
   string m_strName;
   int m_nPrice;
};

class CCar : public CProduct
{
public:
   CCar(string strName, int nPrice) { m_strName = strName; m_nPrice = nPrice; };
   virtual ~CCar() {};

   virtual string ToString() {
      ostringstream sout;
      sout << "Name: " << m_strName << ", Price: $" << m_nPrice;
      return sout.str();
   }
private:
   string m_strName;
   int m_nPrice;
};

CFactory 클래스 (추상 팩토리 클래스)
class CFactory
{
public:
   CFactory() {};
   virtual ~CFactory() {};
   virtual CProduct* MakeProduct() = 0;
};

CPhoneFactory, CCarFactory 클래스 (Concrete 팩토리 클래스)
class CPhoneFactory: public CFactory
{
public:
   CPhoneFactory(string strName, int nPrice) { m_strName = strName; m_nPrice = nPrice; };
   virtual ~CPhoneFactory() {};
   CProduct* MakeProduct() {
      return new CPhone(m_strName, m_nPrice);
   }
private:
   string m_strName;
   int m_nPrice;
};

class CCarFactory : public CFactory
{
public:
   CCarFactory(string strName, int nPrice) { m_strName = strName; m_nPrice = nPrice; };
   virtual ~CCarFactory() {};
   CProduct* MakeProduct() {
      return new CCar(m_strName, m_nPrice);
   }
private:
   string m_strName;
   int m_nPrice;
};

CProductFactory 클래스 (클라이언트 클래스)
class CProductFactory
{
public:
   static CProduct* GetProduct(CFactory* pFactory) {
      return pFactory->MakeProduct();
   }
};

실행 부분
void main()
{
   auto_ptr<CFactory> apPhoneFactory(new CPhoneFactory("Phone1", 20));
   auto_ptr<CProduct> apPhone(CProductFactory::GetProduct(apPhoneFactory.get()));

   auto_ptr<CFactory> apCarFactory(new CCarFactory("Car1", 20000));
   auto_ptr<CProduct> apCar(CProductFactory::GetProduct(apCarFactory.get()));

   cout << apPhone->ToString() << endl;
   cout << apCar->ToString() << endl;
}

UML - class 다이어그램
참고
  • http://blog.naver.com/phoogu/110013967927
  • http://devsw.tistory.com/58
  • http://seotory.tistory.com/27

댓글 없음:

댓글 쓰기

참고: 블로그의 회원만 댓글을 작성할 수 있습니다.