Недавно я слышал об абстрактном шаблоне фабрики, и в настоящее время у меня есть некоторые сомнения относительно того, как создать такой шаблон, когда нужны параметризованные конструкторы.
Точнее, из того, что я понял, одно из главных преимуществ этого шаблона проектирования
это облегчает управление кодом, так как всякий раз, когда в систему вводится новый тип, нужно адаптировать одну фабричную функцию, в которой вызываются конструкторы объектов.
В большинстве примеров, которые я нашел, рассматриваются только пустые конструкторы (скажем, конструкторы по умолчанию).
Но что произойдет, если понадобится использовать параметризованные конструкторы? Этот шаблон дизайна все еще работает?
Поскольку параметры могут отличаться по типу и количеству между производными классами,
нужно учитывать несколько заводских функций?
Ниже я привожу пример того, чего я хотел бы достичь. Обратите внимание, что для сокращения строк кода я рассмотрел только один конструктор на класс, который служит как конструктор по умолчанию, так и параметризованный конструктор.
class Shape {
public:
Shape(){std::cout << "Calling Shape Constructor\n";};
virtual ~Shape(){std::cout << "Calling Shape Desstructor\n";};
virtual void draw() const = 0;
virtual void doSomething1(int) const = 0;
virtual void doSomething2(int, float) const = 0;
};
class Rectangle : public Shape {
public:
Rectangle(int l = 0, int b = 0 ):l(l),b(b){ std::cout << "Calling Rectangle Constructor\n"; };
~Rectangle(){ std::cout << "Calling Rectangle Destructor\n\n"; };
virtual void draw() const{ /* Draw Rectangle */ };
virtual void doSomething1(int) const { /* doSomething1 */};
virtual void doSomething2(int, float) const { /* doSomething2 */};
private:
int l,b;
};
class Circle : public Shape {
public:
Circle(int r = 0):r(r){ std::cout << "Calling Circle Constructor\n"; };
~Circle(){ std::cout << "Calling Rectangle Destructor\n\n"; };
virtual void draw() const{ /* Draw Circle*/ };
virtual void doSomething1(int) const { /* doSomething1 */};
virtual void doSomething2(int, float) const { /* doSomething2 */};
private:
int r;
};
class ShapeFactory{
public:
ShapeFactory(int = 0, double = 0);
std::unique_ptr<Shape> CreateShape(const std::string & );
~ShapeFactory();
};
std::unique_ptr<Shape> ShapeFactory::CreateShape(const std::string & type /*, int rad, int side1, int side2, .... */) {
if ( type == "circle" ) return std::unique_ptr<Shape>(new Circle( /* rad */)); // Should call Circle(int rad)!
if ( type == "rectangle" ) return std::unique_ptr<Shape>(new Rectangle( /* side1, side2 */)); // Should call Rectangle(int, int)!
// if ( type == "someNewShape") return std::unique_ptr<Shape>(new someNewShape( /* param1, param2, ... */)); // Should call someNewShape(param1, param2)!
throw std::invalid_argument("MobileFactory: invalid type: " + type);
}
У меня также есть еще одно сомнение. Представьте, что из-за некоторых потребностей мне нужны члены класса для класса "ShapeFactory". То, что я хотел бы сделать интуитивно, это что-то вроде:
std::vector< std::unique_ptr<ShapeFactory2> > mylist;
mylist.push_back( new ShapeFactory2(CreateShape("circle",radius), param1, param2) );
mylist.push_back( new ShapeFactory2(CreateShape("rectangle",side1,side2), param1, param2) );
for (std::vector< std::unique_ptr<ShapeFactory2> >::const_iterator it = v.begin(), end = v.end(); it != end; ++it)
{
int param1 = it->param1;
float param2 = it->param2;
it->doSomething2(param1, param2);
// or equivalently
Shape * myShape = *it;
int param1 = it->param1;
float param2 = it->param2;
myShape->doSomething2(param1, param2);
}
Как изменится объявление класса ShapeFactory для этого конкретного случая? Буду ли я теперь smart_pointer в качестве члена класса, кроме param1, param2? Если да, кто-нибудь может проиллюстрировать, как реализовать конструкторы / деструкторы?
Все предложения / идеи действительно приветствуются! ; -)