如何将数据传递给使用工厂方法创建的对象

问题描述:

我正在通过工厂方法模式创建一系列对象。或多或少像这样:如何将数据传递给使用工厂方法创建的对象

class CMyFactory 
{ 
public: 
    virtual CMyObject* MakeObject(ObjectType type); 
} 


CMyObject* CMyFactory::MakeObject(ObjectType type) 
{ 
    CMyObject* newObject = NULL; 
    switch (type) 
    { 
    case type1: 
     newObject = new CType1Object; 
     break; 
    case type2: 
     newObject = new CType2Object; 
     break; 

    // Other cases here 
    } 
    returm newObject; 
} 

现在,假设我想将一些数据传递给创建的具体对象。根据我想要创建的对象的类型,这些数据会有所不同。

有没有这样做的干净方式?

我想我可以在创建对象后传递数据,但这不适合工厂。工厂方法的想法是仅将对象创建的逻辑放在一个地方。所以,如果以后我必须处理对象类型相关的类,那么直接创建我想要的类型的对象并没有多大区别。

关于如何解决这个问题的任何想法?也许工厂方法模式不是我需要的吗?

我希望我明确自己。

有一两件事你可以做的是它传递给构造,像这样:

class CMyFactory 
{ 
public: 
    virtual CMyObject* MakeObject(ObjectType type, ParamType param); 
} 


CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param) 
{ 
    CMyObject* newObject = NULL; 
    switch (type) 
    { 
    case type1: 
     newObject = new CType1Object(param); 
     break; 
    case type2: 
     newObject = new CType2Object(param); 
     break; 

    // Other cases here 
    } 
    return newObject; 
} 

可以根据参数类型重载MakeObject,像这样:

class CMyFactory 
{ 
public: 
    virtual CMyObject* MakeObject(ObjectType type, ParamType param); 
    virtual CMyObject* MakeObject(ObjectType type, OtherParamType param); 
} 

CMyObject* CMyFactory::MakeObject(ObjectType type, ParamType param) 
{ 
    CMyObject* newObject = NULL; 
    switch (type) 
    { 
    case type1: 
     newObject = new CType1Object(param); 
     break; 
    case type2: 
     newObject = new CType2Object(param); 
     break; 

    // Other cases here 
    } 
    return newObject; 
} 


CMyObject* CMyFactory::MakeObject(ObjectType type, OtherParamType param) 
{ 
    CMyObject* newObject = NULL; 
    switch (type) 
    { 
    case type3: 
     newObject = new CType3Object(param); 
     break; 
    case type4: 
     newObject = new CType4Object(param); 
     break; 

    // Other cases here 
    } 
    return newObject; 
} 

这种方法具有的disadvan保证你的工厂的用户需要知道它需要传递哪种类型的对象以创建哪种类型的对象,但这对于这种方法来说可能是不可避免的。

我想我可以在创建对象后传递数据,但这不适合工厂。工厂方法的想法是仅将对象创建的逻辑放在一个地方。所以,如果以后我必须处理对象类型相关的类,那么直接创建我想要的类型的对象并没有多大区别。

我同意:您不应该在创建后将数据传递给对象。这相当于两步创造,这有损于目的。

尽管使用工厂方法并不能隐藏构造对象的方式:它也可以隐藏创建的对象的实际类型。一个典型的例子是WidgetFactory,它将创建各种小部件,但总是会返回Widget*,允许您的代码在处理创建的小部件时利用多态性 - 并允许库实现者在幕后更改实现而不会破坏客户端代码

数据是否完全不同?或者是完全不同的对象?

例如,他们都是交易,但一个是现金,一个是支票,一个是信用卡?在这种情况下,数据(金额,日期等)和一些不同的数据(例如卡号)会有一些共同点?

在这种情况下,您可以创建一个基类(例如CTransaction)并为CCreditTransaction等进行继承。然后您可以让您的MakeObject也接受一个CTransaction对象。

如果我们在谈论CType1Object是一个Transaction,而CType2Object是库存系统中的一个项目,CType3Object是一些小部件,那么我认为您不需要调整您的实现。

你的工厂可能是像MakeTransaction(...),并有MakeWidget一个单独的工厂(......)和一个单独的工厂MakeInventoryItem(...)等

+0

这些对象都来自同一个基类,但数据可能不同。如果它是相同的,我只是将另一个参数添加到工厂方法并将其传递到那里。 – MikMik 2011-03-30 14:57:17

在反序列化的情况下,这非常简单:在串行流中,有一些令牌(枚举类型),工厂可以从中决定要创建哪个对象。然后串行流可以通过虚拟反序列化()函数传递给对象。在所有对象知道流中的什么格式数据对他来说最好之后。

否则,可能会使用双重调度机制:您想创建一些对象,因此数据应该是兼容的。但是,C++不支持double dispatch,因此实现它非常麻烦(还有依赖性)。

我不知道我是否正确地理解了这个问题。你说你有参数传递给工厂方法,这取决于要创建的类型。如果你足够了解创建正确的一组参数,(如果你知道要传递什么ObjectType),那么为什么要有一个工厂,为什么不直接创建对象呢?工厂的想法是隐藏类型,但在这里你(隐式地)暴露类型。

+0

那么,我有几个相同基类型的对象,我想集中他们的创作。这样,客户端只需要知道对象类型(枚举)而不是它们的声明(当添加新对象类型时不需要包含新的* .h文件)。大多数对象不需要附加的附加数据,但有些可以。 – MikMik 2011-03-30 15:11:44

+0

在此解决方案中,如果添加新类型,则需要扩展枚举并更改工厂方法。我不相信避免使用'#include's是值得的额外的复杂性,即使不需要参数化对象创建。 – Pete 2011-03-30 15:33:30