关于纯抽象类中的静态成员函数-设计模式
about static member functions in pure abstract classes - design pattern?
我最近发现了一个在pure abstract classes
中使用static member functions
初始化指向其派生类对象的指针的示例。我想知道,这是一种设计模式,还是一种良好的编程实践?下面的代码只是一个示例(例如defineRectangle() and defineCircle()
成员功能):
class Shape;
typedef std::unique_ptr<Shape> shape_ptr;
class Shape{
public:
Shape(){};
virtual ~Shape(){};
virtual void draw() const = 0;
virtual float area() const = 0;
virtual shape_ptr clone() const = 0;
virtual shape_ptr create() const = 0;
static shape_ptr defineRectangle(int, int );
static shape_ptr defineCircle(float);
};
shape_ptr Shape::defineRectangle(int height, int width){
shape_ptr ptrRectangle = shape_ptr(new Rectangle(height, width));
return (ptrRectangle);
}
shape_ptr Shape::defineCircle(float radius){
shape_ptr ptrCircle = shape_ptr(new Circle(radius));
return (ptrCircle);
}
最终目标是定义一个derived classes
的容器。例如:
std::vector<std::unique_ptr<Shape> > vect;
然后我们可以通过调用Shape
类的静态成员函数在容器中添加派生类:
vect.push_back(Shape::defineCircle(10));
vect.push_back(Shape::defineRectangle(5, 4));
或直接无任何接口:
vect.push_back(std::unique_ptr<Shape>(new Circle(10)));
vect.push_back(std::unique_ptr<Shape>(new Rectangle(5,4)));
在容器中添加派生类的两种方式中,哪一种应该是首选,为什么
完整的代码可以在以下链接中找到
上面的任何灯都非常受欢迎;-)
我想知道,这是一种设计模式,还是一种良好的编程实践?
是的,这是工厂模式的变体。
基本上,它允许您拥有一个单独的方法,该方法将根据该方法的参数来调度正确派生对象类型的动态创建。这允许您在代码中使用相同的"工厂"函数,如果对工厂方法创建的底层对象有任何更改或添加,则不必更改实际调用"工厂"功能的代码。因此,它是一种封装形式,将对象创建的任何更改隔离到"工厂"后面的代码段,而不是调用"工厂"的代码。例如,使用工厂,添加工厂方法可以创建的新类型相对简单,但调用工厂的以前代码都不必更改。您只需要为要创建的新对象创建一个新的派生类,对于任何需要该新对象的新代码,都需要传递正确的新参数。所有旧的参数仍然有效,并且代码中不需要对返回的指针类型等进行更改。
在工厂中使用智能指针的原因是为了避免指针所有权不明确时可能发生的内存泄漏。例如,工厂必须返回一个指针,因为它正在动态地创建对象。然后问题就变成了谁清理指针以避免悬挂指针或内存泄漏?智能指针解决了这个所有权问题,并保证当其他对象仍指向内存时,内存不会被无意中清理干净,或者内存不会因为指向该内存位置的最后一个指针超出范围而丢失,而没有调用delete
。
我建议不要将工厂方法放在基类中,因为从技术上讲,Shape
对Rectangle
或Circle
一无所知。如果您添加一个新形状,例如Donut
,那么您会怎么做?在Shape
中添加新的工厂方法?你很快就会把界面弄得一团糟。因此,国际海事组织认为,第二种方法会更好。
如果您想减少每次创建shape_ptr
a的繁琐程度,您可以始终将工厂方法移动到适当的子类:
class Circle : public Shape
{
// ...
public:
static shape_ptr make(float radius)
{
return shape_ptr(new Circle(radius));
}
};
// ...
vect.push_back(Circle::make(5.0f));
由于有std::unique_ptr
,我假设编译器支持C++11。在这种情况下,让我提供第三种选择:
vect.emplace_back(new Circle(10));
vect.emplace_back(new Rectangle(5,4));
(关于.emplace_back
:push_back vs template_back)
这样就不需要重复shape_ptr
,也不需要在添加新子类时向Shape
声明新的工厂方法。
编辑:在C++14中,可以使用std::make_unique
来摆脱原始的new
调用。
vect.emplace_back(std::make_unique<Circle>(10));
vect.emplace_back(std::make_unique<Rectangle>(5, 4));
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 确保所有构造函数调用相同的函数 c++ 设计模式
- 设计模式,以避免不必要地添加抽象函数以适应新功能
- sql记录集函数的状态设计模式
- 设计模式的工厂替代方法:具有不同构造函数的类
- 从对象成员函数内部删除操作的技术 /设计模式
- 正确的方法或设计模式,以简化类中的“operatorX”函数,以按给定顺序比较相同类型的属性
- 依赖注入/继承设计模式的构造函数参数太多
- 单例设计模式 - 显式声明类外的构造函数
- 静态函数的单元测试设计模式
- Decorator设计模式:为什么调用链中的函数而不调用循环中的函数
- 使用设计模式时"指向函数的指针"的优点
- 在单例设计模式中使用复制构造函数和赋值运算符
- 在最终类中调用静态方法的静态基构造函数的设计模式
- 如何在不使用非构造函数的方法的情况下应用singleton设计模式来返回类对象
- 如何在PIMPL设计模式中调用参数化构造函数
- 关于纯抽象类中的静态成员函数-设计模式
- 基类函数调用的替代设计模式
- 模板实例化的抽象基类的子类的构造函数-需要替代设计模式
- 设计模式-在C++中返回对象集合的函数