工厂方法在这里适用吗?

时间:2010-07-12 08:15:10

标签: c++ design-patterns factory

我正在生成一系列Step个对象,这些对象因“类型”和其中包含的数据而不同。 e.g:

Step对象基本上应该是看起来像这样的结构

{ GRAB, CASCADE_ONE, FACEUP, SOMEOTHERDATA },
{ DROP, DECK,  FACEDOWN, MOREDATA, ANDSOMEMORE },
{ MOVE, 34, 89 },

其中GRABMOVEDROP表示StepType

typedef enum
{
     GRAB,
     DROP,
     MOVE
}StepType;

正如您所看到的,根据StepType,这些结构在StepType之后都有可变数量的数据字段。

我计划迭代这些结构的序列,并根据StepType字段执行特定操作。我的第一个预感是这些应该是从抽象Step类派生的类的对象 - 即我应该创建一个GrabStep类,一个MoveStep类和一个DropStep类。

这是一个好的设计,如果是这样,我应该使用工厂方法创建它们吗?如果要采用工厂方法,那么如何初始化对象中的字段?

3 个答案:

答案 0 :(得分:4)

您不需要工厂模式。但是创建一个抽象的Step类是一个好的开始:

class Step
{
private:
    // The presence of a pure virtual makes this class abstract.
    virtual void DoAction() = 0;
public:
    virtual ~Step() {} // Needed if you are going to delete via a Step* pointer
    void Action() { DoAction(); } // Template method pattern
};

// All other classes derive publicly from Step, since they all have an "is-a"
// relationship with Step (i.e. a GrabStep "is-a" Step).
class GrabStep : public Step
{
private:
    void DoAction() { /* Do whatever a GrabStep does */ };
    // Data relevant to GrabStep
};

class MoveStep : public Step
{
private:
    void DoAction() { /* Do whatever a MoveStep does */ };
    // Data relevant to MoveStep
};

class DropStep : public Step
{
private:
    void DoAction() { /* Do whatever a DropStep does */ };
    // Data relevant to DropStep
};

然后,你可以迭代这些事情,而不必知道它们的确切类型:

// Example:
std::vector<Step*> seq; // or some other container
// Note that we are storing Step* pointers in a container instead of Step
// objects. This is needed for polymorphism to work.
// ...
seq.push_back(new GrabStep);
seq.push_back(new MoveStep);
seq.push_back(new DropStep);
// ...
for(std::vector<Step*>::iterator i = seq.begin(); i != seq.end(); ++i)
{
    // Will call the proper version of DoAction() depending on the actual type.
    (*i)->Action();
}
// ...
// After we are done, clean up after ourselves. This is needed because
// std::vector does not delete the pointees.
for(std::vector<Step*>::iterator i = seq.begin(); i != seq.end(); ++i)
{
    delete (*i); // Safe because Step has a virtual destructor.
}

答案 1 :(得分:1)

从它的声音中你所需要的只是某种类型的多态性,你可以使用抽象基类。

工厂模式是指调用者不关心他们将需要的对象的类型,只是它符合接口。例如,配置文件的解析器不关心配置文件的位置,或者它是二进制文件还是xml。解析器想要做的就是读取元素。

在您的情况下,无论代码选择通过定义构造哪个步骤类型,都要关注他们正在创建的对象类型。您仍然可以使用工厂模式来抽象构造,但是每个步骤类型需要一个工厂函数(具有相关参数)。

根据您用来决定构建哪个步骤类型的方法,您可能希望将它们抽象为策略模式或类似方法。

答案 2 :(得分:1)

如果你需要运行时多态性,那么我认为这是一个很好的设计。关于工厂功能:如果您的客户需要一个,请写一个。工厂函数只是调用子类的构造函数。