如何使用工厂方法创建不同的对象
how to create different objects with factory methods
我浏览了工厂设计模式并产生了一些疑问, 我在register
函数中看到的代码,
他们将对象存储在map
中(注册时,第一次创建对象并将它们存储在容器类中),每当我们需要对象时,我们必须从工厂询问(Factory::getObject("Rectangle")
),这个矩形是在注册期间已经创建并存储在地图中,并且每当我调用getObject("Rectangle")
时,他们都会返回此对象)。
我的怀疑是每次我只得到相同的对象,如果我想为矩形创建 10 个不同的对象,
如何创建此矩形的 10 个差异对象?
提前谢谢。
RangeRingsFactory::RangeRingsFactory()
{
Register("Big", &Picture::Create); //picure & picyureInPicture inherited from IRangeRings
Register("Small", &PictureInPicture::Create);
}
RangeRingsFactory *RangeRingsFactory::Get()
{
static RangeRingsFactory instance;
return &instance;
}
void RangeRingsFactory::Register(const string &Name, CreateRRFn pfnCreate)
{
map1[Name] = pfnCreate;
}
IRangeRings *RangeRingsFactory::CreateRR(const string &Name)
{
FactoryMap::iterator it = map1.find(Name);
if( it != map1.end() )
return it->second();
return NULL;
}
图片:
Picture::Picture():IRangeRings()
{
setRangeScale(QRect(-200,-200,400,400));
}
IRangeRings *Picture::Create()
{
return new Picture();
}
主要:
MainWindow::MainWindow(QWidget *parent)
: QWidget(parent)
{
string Name1 = "Big";
IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR(Name1);
string Name2 = "Small";
IRangeRings *p2 = RangeRingsFactory::Get()->CreateRR(Name2);
outerLayout = new QHBoxLayout;
outerLayout->addWidget(p1);
outerLayout->addWidget(p2);
this->setLayout(this->outerLayout);
}
您似乎正在考虑"原型"和"工厂"模式的组合。 工厂允许客户端"注册"原型实例,这些实例可能是某些公共基的子类。 然后,"getObject"方法生成所请求原型的副本。
我做了一个快速的谷歌"原型模式c ++"......以下是众多结果中的两个:
http://en.wikibooks.org/wiki/C%2B%2B_Programming/Code/Design_Patterns#Prototype
http://www.codeproject.com/Articles/185348/Prototype-Design-Pattern-2
下面是一个简单的示例,使用基类shape
和两个子类rectangle
和circle
。 这些类的作用不大,但它们具有说明模式的最小结构。
(警告:我实际上并没有编译这个,所以如果我犯了任何简单的错误,请让我休息一下!
#include <map>
// Abstract base class for all shapes
class shape
{
public:
virtual ~shape() {}
virtual shape* clone() const = 0;
};
// Concrete subclass of shape
class rectangle : public shape
{
public:
virtual shape* clone() const override
{
return new rectangle( *this );
}
};
// Concrete subclass of shape
class circle : public shape
{
public:
virtual shape* clone() const override
{
return new circle( *this );
}
};
class Factory
{
public:
// Add the given prototype object to the factory
void register( std::string name, shape* proto )
{
protos[name] = proto;
}
// Get a copy of the prototype with the given name
shape* getObject( std::string const& name ) const
{
// Warning: This will throw if name is not found!
return protos[name]->clone();
}
private:
// Warning: This will leak unless cleaned up in the destructor!
std::map<std::string, shape*> protos;
};
int main()
{
Factory fact;
fact.register( "rectangle", new rectangle() );
fact.register( "circle", new circle() );
// These will be separate copies of the original prototype
shape* rect1 = fact.getObject( "rectangle" );
shape* rect2 = fact.getObject( "rectangle" );
// Don't leak!
delete rect1;
delete rect2;
}
注意:我知道有很多方法可以改进此代码,但我尽量保持简单以避免分散关键点的注意力。
工厂存储字符串映射到"创建函数"。 在其构造函数中,它注册了其中两个:"大"对应于Picture::Create
,"小"对应于PictureInPicture::Create
。
CreateRR
方法查找给定的Name
,调用相应的创建函数,并返回其结果。
只要Picture::Create
和PictureInPicture::Create
都产生新对象,每次调用CreateRR
时都会得到一个新对象。
所以事实上你有...
-
两个工厂函数 -
Picture::Create
和PictureInPicture::Create
- 每个函数始终创建相同类型的对象 -
一个工厂类 -
RangeRingsFactory
- 向您隐藏特定类型(Picture
和PictureInPicture
),因此您可以简单地按名称("大"或"小")请求一个,而无需知道或关心产生的特定对象类型。
解决方案 A
如果在创建IRangeRings
时设置了不同的矩形,它将在 IRangeRings中具有不同的矩形。
更改这些功能:
CreateRRFn()
IRangeRings *RangeRingsFactory::CreateRR(const string &Name)
IRangeRings *Picture::Create()
自:
CreateRRFn(QRect rect)
IRangeRings *RangeRingsFactory::CreateRR(const string &Name, const QRect &rect)
IRangeRings *Picture::Create(const QRect &rect)
然后使用 RangeRingsFactory
实例创建新IRangeRings
,如下所示:
IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR("Big", QRect(0, 0, 100, 100));
解决方案 B
你也可以在IRangeRings
中添加一个新的纯virtual
函数,(我认为IRangeRings
是一个接口类),我把它命名为ToSetRangeScale
。Picture
和PictureInPicture
必须实现它:
void Picture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }
void PictureInPicture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }
然后在创建 Picture
或 PictureInPicture
的对象后调用 ToSetRangeScale
来设置 rect
IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR("Big");
p1->ToSetRangeScale(QRect(0, 0, 100, 100));
最后
该RangeRingsFactory
存储Create
函数的一些指针。同一函数可以创建具有相同类的不同对象。不同的函数可以创建具有不同类的不同对象。如果要更改新对象的属性,可以在创建对象时或通过 new 方法创建对象之后设置该属性。
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 具有包含其他对象的类的对象创建顺序
- 为什么我们再次从结构对象创建结构变量?
- 将对象创建为全局/静态对象会崩溃,而本地对象不会崩溃
- 如何创建一个对象创建函数,该函数将由与其关联的名称调用?
- 如何为自定义模板对象创建专门的函数模板
- 对象创建错误的C++矢量
- 如何为Python Swigged C++对象创建和分配回调函数
- 在 C++ 中为 C 样式对象创建一个透明包装类
- 此类模板的对象创建如何工作?
- C++ 中的对象创建类型有什么区别?
- 未知大小的数组作为类成员,用于在运行时(对象创建时间)创建数组的对象
- 如何仅通过父类对象限制对象创建
- 在正确性或良好的代码结构方面,这种动态对象创建看起来如何
- 无法将类对象创建为另一个类的成员
- 如何从现有基类对象创建派生类对象
- 在 DTor 之前删除的静态对象创建的线程?
- C++:定义多个构造函数时的对象创建/销毁序列
- 从对象创建矢量包装器,该对象只允许使用索引访问向量
- 是否可以为CPP中的对象创建一组指针