gpt4 book ai didi

c++ - 具有参数化构造函数的抽象工厂

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:45:39 24 4
gpt4 key购买 nike

我最近听说了抽象工厂模式,目前对在需要参数化构造函数时如何设计这种模式有一些疑问。

更准确地说,据我了解,这种设计模式的主要好处之一是为了便于代码管理,因为每当向系统引入一种新类型时,都需要调整一个调用对象构造函数的工厂函数。

我发现的大多数示例仅考虑空构造函数(比如默认构造函数)。
但是,如果需要使用参数化构造函数会怎样?这种设计模式还有效吗?
由于派生类之间的参数类型和数量可能不同,是否需要考虑多个工厂功能?下面我将举例说明我想要实现的目标。请注意,为了减少代码行,我只考虑了每个类一个构造函数,它既用作默认构造函数又用作参数化构造函数。

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”类声明会发生什么变化?除了 param1、param2 之外,我现在还会有一个 smart_pointer 作为类(class)成员吗?如果是,谁能说明如何实现构造函数/析构函数?

非常欢迎所有建议/想法! ;-)

最佳答案

只有当派生对象的签名足够相似以支持公共(public)构造函数签名时,工厂模式才真正适用。这是一种常见的情况,因为对象适合共享虚函数签名,因此构造函数也相似。在您的示例中,从中心点和区域构建形状适合工厂模式。

如果构造函数完全不同,工厂模式就毫无意义,应该避免使用。当不使用工厂时,您提供的用法示例更加清晰和安全。

我将使用我最近代码中的参数为您提供一个合理的工厂的简短示例:假设您想要将一个函数拟合到图像的像素。有两种可能的计算方式,不相交(行和列彼此分开)和 union 。不相交拟合更便宜,但对于某些数据来说是不可能的。这些计算方式由两个不同的类支持,DisjointFitter 和 JointFitter,它们接收数据作为它们的参数并且都派生自 Fitter。工厂看起来像:

std::auto_ptr<Fitter> Fitter::create( const Data& data ) {
if ( data.supports_disjoint_fitting() ) {
return std::auto_ptr<Fitter>( new DisjointFitter(data) );
} else {
return std::auto_ptr<Fitter>( new JointFitter(data) );
}
}

在形状上有些做作的术语中,它可能看起来像:

enum BasicShape { Round, Edgy };
mylist.push_back( ShapeFactory::CreateShape( Round, 16 ) );

抽象工厂方法看起来像:

static std::unique_ptr<Shape> CreateShape(BasicShape shape, double area) {
if ( shape == Round )
return std::unique_ptr<Shape>( new Circle( sqrt(area / M_PI) ) );
else
return std::unique_ptr<Shape>( new Square( sqrt(area) ) );
}

关于c++ - 具有参数化构造函数的抽象工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8287441/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com