C++ 객체 팩토리(Object Factory)
C++ 2008. 6. 4. 10:53 |여러개의 객체를 생성하는 코드를 아래와 같이 일반적으로 사용합니다.
class Shape {};
class Line_ : public Shape { public: Line_() { printf("create Line\n"); } };
class Polygon_ : public Shape { public: Polygon_() { printf("create Polygon\n"); } };
class Circle_ : public Shape { public: Circle_() { printf("create Circle\n"); } };
namespace DrawingType
{
const int
LINE = 1,
POLYGON = 2,
CIRCLE = 3;
};
Shape* Load( int drawingType )
{
Shape* p;
switch( drawingType )
{
using namespace DrawingType;
case LINE:
{
p = new Line_();
}
break;
case POLYGON:
{
p = new Polygon_();
}
break;
case CIRCLE:
{
p = new Circle_();
}
break;
}
return p;
}
사용은 아래와 같이
Shape* p;
p = Load( DrawingType::LINE );
delete p;
p = Load( DrawingType::POLYGON );
delete p;
p = Load( DrawingType::CIRCLE );
delete p;
하지만 이런 코드의 경우 객체의 추가로 인한 오버헤드가 커지게 됩니다.
그럼 이런 경우 어떻게 조금더 최적화가 가능해질것인가를 생각해 보면 아래와 같이 될 수 있습니다.
//
class ShapeFactory
{
ShapeFactory() {}
public:
typedef Shape* (*CreateShapeCallback)();
static ShapeFactory& GetInstance()
{
static ShapeFactory sf;
return sf;
}
private:
typedef std::map< int, CreateShapeCallback > CallbackMap;
public:
bool RegisterShape( int ShapeId, CreateShapeCallback CreateFn )
{
return callbacks_.insert(
CallbackMap::value_type( ShapeId, CreateFn ) ).second;
}
bool UnRegisterShape( int ShapeId )
{
return callbacks_.erase( ShapeId ) == 1;
}
Shape* CreateShape( int ShapeId )
{
CallbackMap::const_iterator I = callbacks_.find( ShapeId );
if( I == callbacks_.end() )
return NULL;
return (I->second)();
}
private:
CallbackMap callbacks_;
};
namespace
{
Shape* CreateLine()
{
return new Line_;
}
Shape* CreatePolygon()
{
return new Polygon_;
}
Shape* CreateCircle()
{
return new Circle_;
}
};
// 사용할때
// 객체 레지스트리에 등록
ShapeFactory::GetInstance().RegisterShape( DrawingType::LINE, CreateLine );
ShapeFactory::GetInstance().RegisterShape( DrawingType::POLYGON, CreatePolygon );
ShapeFactory::GetInstance().RegisterShape( DrawingType::CIRCLE, CreateCircle );
p = ShapeFactory::GetInstance().CreateShape( DrawingType::LINE );
delete p;
p = ShapeFactory::GetInstance().CreateShape( DrawingType::POLYGON );
delete p;
p = ShapeFactory::GetInstance().CreateShape( DrawingType::CIRCLE );
delete p;
객체를 레지스트리에 등록하고
사용하게 됩니다.
이때 더 나아간다면 템플릿을 사용해서 예외 처리를 조금더 기능적으로 해줄 수 있습니다.