我经历了工厂设计模式,并有一些疑问,
我在register
函数中看到的代码,
他们将对象存储在map
(注册,第一次创建对象并将它们存储在容器类中),每当我们需要我们必须要求的对象时factory(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);
}
答案 0 :(得分:0)
看起来你正在考虑“原型”和“工厂”模式的组合。工厂允许客户“注册”原型实例,这些实例可能是某些共同基础的子类。然后“getObject”方法生成所请求原型的副本。
我为“原型模式c ++”做了一个快速的Google ...以下是众多结果中的两个:
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;
}
注意:我知道有很多方法可以改进这些代码,但我试图保持简单,以避免分散注意力。
答案 1 :(得分:0)
工厂将字符串映射存储到“创建函数”。在它的构造函数中,它注册了两个:“Big”对应Picture::Create
,“Small”对应PictureInPicture::Create
。
CreateRR
方法查找给定的Name
,调用相应的创建函数,并返回其结果。
只要Picture::Create
和PictureInPicture::Create
都生成新对象,每次调用CreateRR
时都会获得一个新对象。
所以事实上你有......
两个工厂函数 - Picture::Create
和PictureInPicture::Create
- 每个函数始终创建相同类型的对象
一个工厂类 - RangeRingsFactory
- 隐藏了您的特定类型(Picture
和PictureInPicture
),因此您只需要一个按名称(“大”或“小”),不知道或关心所产生的具体对象类型。
答案 2 :(得分:0)
如果在创建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));
您还可以在virtual
中添加新的纯IRangeRings
函数,(我认为IRangeRings
是一个接口类),我将其命名为ToSetRangeScale
。
Picture
和PictureInPicture
必须实现它:
void Picture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }
void PictureInPicture::ToSetRangeScale(const QRect &rect) { setRangeScale(rect); }
然后在创建ToSetRangeScale
或Picture
的对象后调用PictureInPicture
设置矩形:
IRangeRings *p1 = RangeRingsFactory::Get()->CreateRR("Big");
p1->ToSetRangeScale(QRect(0, 0, 100, 100));
RangeRingsFactory
存储Create
函数的一些指针。相同的函数可以创建具有相同类的不同对象。不同的函数可以创建具有不同类的不同对象。如果要更改新对象的属性,可以在创建对象时或在通过新方法创建对象后设置属性。