2014-10-01 56 views
0

我正在實施組件創建的工廠模式,並且希望爲工廠創建的每種類型的所有實例實現一個單身容器。理想情況下,這將是工廠中創建的每種類型的一個向量。C++工廠模式組件創建者與單身容器

如果我可以在向量中保留基類指針,但是很抱歉,我的用例會大大優先選擇所有實例連續存儲,而不是在新的位置放置它們以獲取儘可能多的緩存命中。

我考慮做這樣的事情了工廠地圖:

Map<string,pair<constructorFnPtr, vector<baseClass>> 

這與它被強制轉換爲基類派生類丟失數據的問題。

我也在想,作爲這一對的第二個成員的向量指針是一個很好的方法來做到這一點,但我不知道如何實現這一點,同時仍然有不同的數據類型存儲在每個矢量。我不認爲這是可能的,因爲模板載體在技術上都是不同的類別。

有沒有辦法做我想做的事情?過去幾天我一直在試圖找出一些事情,但沒有運氣。

或者,如果有另一種好的方法來存儲向量(即作爲組件類的靜態成員),我也歡迎任何建議!

+0

嘗試使用'dynamic_cast'獲取所需的類型,但是如果實例不是該類型,它將返回null或拋出:'dynamic_cast (myour_map [「instance」]。second [0])'if「實例「不是'TypeIWant',它將返回null或拋出(基於編譯器設置) – Raxvan 2014-10-01 08:20:05

+0

是的,它用於將實例從工廠中取出,但它不適用於將其放入實例向量中。我不想要一個指針向量,因爲每次迭代時從主內存中獲取它們的開銷都很高。 – 2014-10-01 09:15:06

回答

0

你不能用連續對象的std :: vector來做到這一點。

原因是:一個工廠應該建立對象,然後返回一個指向他們的指針。問題是,該指針將要在應用程序中圍繞存儲,而到your_vector.push_back()下一個電話很可能將它們無效,因爲C++文件說:

如果新的大小()大於容量(),則所有迭代器和引用(包括過去末端迭代器)都將失效。否則只有前端迭代器失效。

因此,您下一次撥打工廠電話可能會使您以前的所有呼叫失效。

+0

我確實說過,對於我的用例來說,指向矢量元素的指針並不是最優的。該索引被存儲。 – 2014-10-09 01:42:09

+0

比你可以創建一個自定義的類智能指針類,由工廠返回,它存儲索引,然後與解除引用運算符在內部調用工廠檢索實際的實例。這個操作明顯比使用直接指針訪問實例要慢,但是你會有連續的內存存儲以及較少的堆分配調用。它可能會更快,也可能會更慢,具體取決於使用情況。我認爲對於一般用法來說,它只是慢一點。 – nyarlathotep108 2014-10-09 07:50:16

+0

直接指針會更快,直到向量需要增長,並且指向任何元素的指針都會失效。感謝您的定製指針的想法,但我沒有想到這一點,它會很適合我!希望我一個星期前就想出了哈哈 – 2014-10-09 11:39:20

1

我不會考慮使用組件的工廠模式,而是使用對象池模式,因爲您可能希望使用工廠模式來管理實體的創建。

我對所有組件使用基類Component類。這使我能夠管理每個組件的一些靜態運行時類型信息並公開一組常用方法。然後我實現了一個接口IComponentPool,這是我的組件對象池的契約。然後我定義了一個從IComponentPool派生的模板類ComponentPool<T>。在這個模板類裏面我管理兩個向量/數組。然後有一個ComponentPoolMap公開一些類似地圖的行爲來查找基於組件類型的ComponentPool<T>

現在在ComponentPool<T>類中,第一個數組是一個用作查找的稀疏數組。它保存了組件位於第二個密集打包數組內的位置的索引偏移量。稀疏數組可以簡單地作爲獲取EntityId並將其轉換爲組件駐留位置的方法。如果需要,可以輕鬆實現更復雜的句柄系統。

這裏的想法是,壓縮密集充當您的連續內存緩衝區,您可以在緊密循環中輕鬆地在緩存友好莊園中迭代,但稀疏數組提供單個實體間的單向間接查找。

現在工廠模式是創建您的EntityEntityId手柄一個實體,並創造一切必要的方面組成一個獸人,殭屍,或者您的遊戲。該工廠充當了一個位於您的遊戲對象系統之上的層,其中您的ComponentPoolMap可能只是該系統的一小部分。

+0

很好的答案。我也有一個問題。另一篇文章(https://gamedev.stackexchange.com/a/59328)表示,像「EntityFactory :: CreatePlayer/CreateBullet」這樣的創建函數失敗了基於組件的設計*的一半目的,但是您的解決方案聲明, 'Orc/Zombie'功能可以。雖然我同意你的意見,但我希望聽到你對這篇文章的更多寶貴意見。謝謝。 – cppBeginner 2018-01-24 02:06:09

+1

作者只是指出,如果你可以將用於創建Orc或殭屍的工廠方法變成數據驅動的方法,該方法可以定義如何構建Orc/Zombie並完成相同的任務,在開發過程中通常有用的快速原型製作的能力。工廠方法是一個很好的起點,如果您發現需要或希望獲得這種靈活性,您可以輕鬆地重構爲數據驅動的原型解決方案。 – Naros 2018-01-24 14:58:38