2010-07-12 63 views
1

我正在生成一個Step對象的序列,它們根據「Type」和其中包含的數據而不同。例如:工廠方法在這裏適合嗎?

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類。

這是一個很好的設計,如果是的話,我應該使用工廠方法創建它們?如果工廠方法是要走的路,那麼如何初始化對象內的字段?

+0

我不太瞭解工廠方法與您的問題有什麼關係。 – ereOn 2010-07-12 08:21:43

回答

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

'步驟'通常需要一個虛擬析構函數。 – Philipp 2010-07-12 08:31:56

+0

+1用於私人虛擬接口。 – tenpn 2010-07-12 08:37:42

+0

@In silico - 'DropStep','GrabStep'類應該如何從'Step''私下或公開地繼承? – BeeBand 2010-07-12 10:01:57

1

從它的所有聲音中,您需要的是某種類型的多態,您將與抽象基類一起使用。

工廠模式是調用者不關心他們將需要的對象的類型,只是它符合一個接口。例如,配置文件的解析器不關心配置文件的存在位置,或者它是二進制文件還是xml文件。所有解析器想要做的是讀取元素。

在你的情況下,無論哪種代碼正在選擇按照定義構造的步驟類型,都會關心它們創建的對象類型。您仍然可以使用工廠模式來抽象化構造,但是您將需要每個步驟類型的一個工廠函數(具有相關參數)。

根據您使用哪種方法來決定要構建哪種類型的步驟,您可能需要將它們抽象爲策略模式或類似模式。

1

如果你需要運行時多態性,然後我認爲這是一個很好的設計。關於工廠功能:如果你的客戶需要一個,然後寫一個。工廠函數只是調用子類的構造函數。