Post List

2015년 1월 4일 일요일

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

Abstract Factory Pattern

유용한 경우
1. 객체 생성 방법을 한 곳에서 독립적으로 관리하고자 할 때
2. 여러 제품군 중 사용할 제품군을 쉽게 선택할 수 있도록 만들고 싶을 때.
3. 관련된 제품들이 Group이 존재하고, 각 Group별로 제품들의 종류가 가을 때
4. 제품들에 대한 클래스 라이브러리를 만들어야 하는데, 그 인터페이스만 드러내고 구현은 숨기고 싶을 때.

장점
1. 객체 생성 코드가 한곳에 있다.
2. 제품군의 교체가 쉽다.

단점
1. 제품군의 개수가 늘어날 수록 Concrete Factory 클래스의 개수도 늘어나야 한다.
2. 제품군에 새로운 제품이 추가되어야 할 경우 모든 Factory 클래스를 수정하여야 한다.

 예를 들어서 UI 들을 모아놓은 Library를 개발해야하다. UI에는 Button 과 Scrollbar가 있고, 디자인 테마로는 Rectangle과 Circle 이 있다. 테마별로 UI들의 모양이 바뀌기 때문에 RectngleButton 과 CircleScrollbar가 같이 사용되는 경우는 절대 없다. 이 것을 간단히 Abstract Factory Method를 이용하여 구현하면 아래와 같다.




//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
  void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
  void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
  void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
  void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 팩토리 인터페이스
class IUIFactory
{
public:
  virtual IButton* createButton() = 0;
  virtual IScroll* createScroll() = 0;
};
 
//------------------------------------------------------------------
// 사각형 팩토리 클래스
class CUIFactory_Rectangle : public IUIFactory
{
public:
  IButton* createButton() override { return new CButtonRectangle; }
  IScroll* createScroll() override { return new CScrollRectangle; }
};
 
//------------------------------------------------------------------
// 동그라미 팩토리 클래스
class CUIFactory_Circle : public IUIFactory
{
public:
  IButton* createButton() override { return new CButtonCircle; }
  IScroll* createScroll() override { return new CScrollCircle; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
  CUIFactory_Rectangle mRectangleFactory;
   
  IButton* pRectangleButton = mRectangleFactory.createButton();
  IScroll* pRectangleScroll = mRectangleFactory.createScroll();
   
  pRectangleButton->print();
  pRectangleScroll->print();
 
  delete pRectangleButton;
  delete pRectangleScroll;
 
  return 0;
}

템플릿을 이용하여 구현하면 아래와 같다.


//------------------------------------------------------------------
// 버튼 인터페이스
class IButton
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 스크롤 인터페이스
class IScroll
{
public:
  virtual void print() = 0;
};
 
//------------------------------------------------------------------
// 사각 버튼 클래스
class CButtonRectangle : public IButton
{
public:
  void print() override { cout << "CButton Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 사각 스크롤 클래스
class CScrollRectangle : public IScroll
{
public:
  void print() override { cout << "CScroll Rectangle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 버튼 클래스
class CButtonCircle : public IButton
{
public:
  void print() override { cout << "CButton Circle" << endl; }
};
 
//------------------------------------------------------------------
// 둥근 스크롤 클래스
class CScrollCircle : public IScroll
{
public:
  void print() override { cout << "CScroll Circle" << endl; }
};
 
//------------------------------------------------------------------
// 추상 팩토리 템플릿 인터페이스 (템플릿 메소드 패턴 적용)
template<typename T>
class AbstractFactory
{
public:
  T* Create() { return createProduct(); }
 
protected:
  virtual T* createProduct() = 0;
};
 
//------------------------------------------------------------------
// 팩토리 템플릿 클래스 (세부 객체 생성 전담)
template<typename T1, typename T2>
class ConcreteFactory : public AbstractFactory<T1>
{
private:
  T1* createProduct() override { return new T2; }
};
 
//------------------------------------------------------------------
// Main
int _tmain(int argc, _TCHAR* argv[])
{
  ConcreteFactory<IButton, CButtonCircle> mCircleFactory;
  ConcreteFactory<IScroll, CScrollRectangle> mRectangleFactory;
 
  IButton* pCircleButton = mCircleFactory.Create();
  IScroll* pRectangleScroll = mRectangleFactory.Create();
 
  pCircleButton->print();
  pRectangleScroll->print();
 
  delete pCircleButton;
  delete pRectangleScroll;
 
  return 0;
}

참조 : http://devsw.tistory.com
         http://copynull.tistory.com



댓글 없음:

댓글 쓰기