GilGil 님의 글을 보고 영감을 얻어 구현해 보았습니다.

MetaClass 를 이용해 인스턴스 생성시 대상 클래스의 생성자 타입 의존성을 없애려는 시도인데 템플릿이 좀 과한듯도 싶네요.


어찌되었건. 인자가 한개건 두개건( 지금은 최대 2개까지만 구현했습니다 ) 혹은 디폴트생성자건 마음대로 골라서

메타클래스에게 클래스 생성을 위임할수 있도록 구현하는데 목적을 두었습니다

일반적인 팩토리 패턴의 구현과는 다소 다른데요.. 설명하자니 길어서 우선 소스부터 적어버려야 겠네요

struct Point
{
 int x;
 int y;
};   class Shape
{
public:
 virtual void Draw() = 0;
};   class Circle : public Shape
{
 public:
  Circle(){printf("Circle Def\n");}
  Circle(bool visible){}
  Circle(Point,int){}
  Circle(Point,Point){printf("Circle Two pts\n");}
  virtual void Draw(){}
};   class Ellipse : public Shape
{
 public:
  Ellipse(){printf("Ellipse Def\n");}
  Ellipse(bool visible){}
  Ellipse(Point,int){}
  Ellipse(Point,Point){printf("Ellipse Two pts\n");}
  virtual void Draw(){}
};   class Triangle : public Shape
{
 public:
  Triangle(){printf("Triangle Def\n");}
  Triangle(bool visible){}
  Triangle(Point,Point,Point){}
  virtual void Draw(){}
};   class Rectangle : public Shape
{
 public:
  Rectangle(){printf("Rectangle Def\n");}
  Rectangle(bool visible){}
  Rectangle(Point,Point){printf("Rectangle Two pts\n");}
  virtual void Draw(){}
};


이런 클래스 들이 있다고 가정했을때

아래와 같이 이용할 수 있습니다.


typedef Constructor<> DefaultConstructor;
typedef Constructor<bool> BooleanConstructor;
typedef Constructor<Point,Point> TwoPointConstructor;   typedef DefaultConstructor::MetaClassList DefMetaList;
typedef TwoPointConstructor::MetaClassList TwoPtsMetaList;   REGISTER_METACLASS( Circle, Shape, DefaultConstructor )
REGISTER_METACLASS( Ellipse, Shape, DefaultConstructor )
REGISTER_METACLASS( Triangle, Shape, DefaultConstructor )
REGISTER_METACLASS( Rectangle, Shape, DefaultConstructor )   REGISTER_METACLASS( Circle, Shape, TwoPointConstructor )
REGISTER_METACLASS( Ellipse, Shape, TwoPointConstructor )
REGISTER_METACLASS( Rectangle, Shape, TwoPointConstructor )
 
int main()
{
 int i;    DefMetaList *def_ml = VMetaClassMap::getMetaClassList<DefaultConstructor>("Shape");
 TwoPtsMetaList *two_ml = VMetaClassMap::getMetaClassList<TwoPointConstructor>("Shape");    if( def_ml )
 {
  DefMetaList::iterator it;
  for(it = def_ml->begin() ; it != def_ml->end(); it++)
   Shape *sh = (Shape*)(*it)->getFactory()->construct();
 }
  
 if( two_ml )
 {
  TwoPtsMetaList::iterator it;
  Point pt;     for(it = two_ml->begin() ; it != two_ml->end(); it++)
   Shape *sh = (Shape*)(*it)->getFactory()->construct(pt,pt);
 }  
 return 0;
}

템플릿 클래스를 사용하기 때문에 사실 카테고리도 "Shape" 와 같은 문자열이 아니라 실제 타입 단위로 지정할 수 있지만

굳이 그렇게 구현하지는 않았습니다. (그런데 글을 쓰면서 보니 그것도 상당히 좋은 기능이라는 생각이 드네요.. ^^; )


또한, 생성자의 매개변수를 템플릿 인자로 받는 Constructor 가 구분자(?) 처럼 사용되기 때문에

예제에서 보인 클래스들 처럼 부모가 같은 클래스가 아니어도 하나의 카테고리로 묶어버릴수 있다는 장점이 있죠.

서로 전혀 상관이 없는 클래스들 일 지라도 단순히 같은 형태의 생성자만 보유하고 있다면

같은 카테고리로 묶어두었다가 리스팅 하고, 인스턴스를 생성할 수 있습니다.


몇년전에 작성했던 Functor 를 기반으로 팩토리 패턴을 나름 확장하고

나름 의미있다고 생각했던 문자열 기반 categorization 정도만 구현한 코드라고 할 수 있겠네요

재미삼에 업무시간에 짬짬히 한거라... 코드가 영 깔끔치 못해도 아이디어 공유차원의 코드니까 이해해 주세용


DeligatingConstruct.tar


아 참고로 g++ version 4.4.3 을 이용했습니다

Posted by 1stPasa

댓글을 달아 주세요