2012-06-10 96 views
0

爲了替換單例模式和一般的「資源管理器」,我提供了一個解決方案。使資源靜止並受到保護。該資源由繼承類的所有孩子共享。它很有用,但我不確定這是不是一個好的方法。 下面是一些代碼來表達我在做什麼(這裏的資源是SF ::紋理):通過繼承共享的靜態受保護資源

class Foo { 
public: 
    Foo() { 
     if(m_texture == nullptr) { 
      //Création et chargement de la texture 
      m_texture = std::unique_ptr<sf::Texture>(new sf::Texture()); 
      m_texture->loadFromFile("..."); 
     } 

    } 

    void draw(sf::RenderWindow& window) = 0; 

protected: 
    static std::unique_ptr<sf::Texture> m_texture = nullptr; 

}; 

class Bar : public Foo { 
public: 
    Bar() 
     : m_sprite(*m_texture) {} 

    void draw(sf::RenderWindow& window) { 
     window.draw(m_sprite); 
    } 

private: 
    sf::Sprite m_sprite; 
}; 

這樣,我的資源是通過所有的孩子共享,並且只初始化一次。 這是一個很好的解決方案,可以替換我將通過引用隨處攜帶的單例或資源管理器。 謝謝!

+0

我自己喜歡這個想法,並且是谷歌搜索,看看你是否得到了我懷疑的性能增益。每次我看到一種模式,我都會看到一種間接成本。這似乎是清除單身人士臭味的一種方法。
這將類元數據放在類的內部。我會進一步說,如果您正在尋找對象創建的性能和靈活性,那麼對其他模式進行這樣的設計也是一個很好的設計,將其他工廠添加爲靜態函數以支持具有不同接口的其他模式。
通過外化獲得什麼好處? –

回答

1

從根本上說,你所要做的是正確的,一個靜態成員將被共享(即完全相同)在所有繼承類中,這樣你只需要一個實例可以爲你節省大量的內存,但是繼承人夫婦問題...我假設你正在使用g ++。

你不能在類聲明中初始化非const成員,所以這個。
static std::unique_ptr<sf::Texture> m_texture = nullptr;
會產生這樣的:
錯誤:ISO C++禁止在類非const靜態成員
你有你的類的源文件中對其進行初始化的初始化,但是外部類。 std::unique_ptr<sf::Texture> Foo::m_texture = nullptr;

其次它不是保存到直接訪問成員字段,總是使用setter和getters,即使在類的函數中,這使得代碼更易於維護。因此,你可以有一個名爲getTexture

static std::unique_ptr<sf::Texture> getTexture() { 
    if(m_texture == nullptr) { 
     //Création et chargement de la texture 
     m_texture = std::unique_ptr<sf::Texture>(new sf::Texture()); 
     m_texture->loadFromFile("..."); 
    } 
    return m_texture; 
} 

靜電功能,而其真正的if語句和函數調用都添加進來的開銷,這是更容易維護,更安全,並在最後一分鐘時加載紋理其真正需要。

回到你的問題,Singleton設計模式非常簡單,主要用於節省內存,因爲只創建了對象的單個實例:)資源管理器是一個完全不同的野獸,他們的目標是集中所有操作需要加載和管理資源,將兩者結合起來,初始化資源管理器的單個實例,然後通過靜態成員字段訪問它,使所有對象都請求資源,這可能是好的或壞的,這取決於什麼你正在努力實現。

軟件設計很難。我可以給出的最好的建議是,在設計系統時,問自己這個問題:「我需要編寫多少行代碼才能引入另一個類似的組件」,您的目標應該是儘可能地減少這種情況,即儘可能多地重複使用儘可能的你已經創建了。

最好的程序員是懶惰的:)不,我不是說複製/粘貼,應該被禁止。

+1

對於你的第一點,我意識到這一點,並使用VS2010。這是簡化,但我像你在外面做的初始化指針。 對於你的第二點,有道理,謝謝。 第三,我不想做一個單身人士,因爲它幾乎是一個全球性的,我不喜歡這些。 最後,我正在做這一切,以學習和獲得良好的想法,所以我可以變得更好。我想在這種情況下探索單身人士和資源管理者的其他選擇。另外,我討厭複製/粘貼,因爲我什麼都不學。 – Rosme

+0

謝謝!我希望更多的程序員會像你一樣思考!如果對象數量很少,單身設計模式就沒有問題,但是一旦對象數量增加,就很難管理它們,這就是爲什麼它很少單獨使用,很多時候我們從不同的設計中借鑑想法實施我們的系統......如果您始終通過設置者/獲取者訪問您的會員,即使在全球範圍內也可以。:) –

+0

也會關注內聚和耦合。 –

0

設計看起來很可疑。我沒有看到使用這個更廣泛使用的Singleton模式(使用函數本地靜態實例)的任何優勢。你可能最好是關閉在定義點用默認Texture初始化m_texture對象(而不是內Foo的構造函數):

static std::unique_ptr<sf::Texture> m_texture(new sf::Texture()); 

數據成員非常適合派生類。基類通常用於定義接口。

我建議您將資源管理器類(Foo)分開,而不是繼承它,請調用相應的成員函數以訪問Texture對象。

+0

它是靜態的這一事實使得我只得到對象的一個​​初始化,並且只有在它的值爲nullptr的情況下。它可以工作,你可以嘗試在if語句中放置一個'std :: cout <<「Init」;並且它只會出現一次,即使在創建兩個Bar對象時也是如此。 – Rosme

+1

啊。是。我的錯。我錯過了「if」測試。無論如何,這仍然不是一個很好的實施方式。數據成員非常適合派生類。基類通常用於定義接口。我建議你看看句柄身體/ pimpl成語。 – dirkgently

+0

這就是我問的原因。它運作良好,但我確實不確定。去看看這個成語。謝謝。 – Rosme