2012-09-28 113 views
1

我正在爲C++中的項目設計一些類,但我遇到了問題。 我想創建一個camera類,它包含所有需要的值(例如轉換矩陣),但是呈現camera的函數應該是可交換的。這聽起來像是戰略模式的常見案例。因此,我創建了一個界面,該界面定義了render-function,並將camera類別pointer賦予此界面。 問題是render function需要訪問camera類中的所有數據,因此我給這個函數一個指向camera類的指針作爲參數。它看起來像這樣:遞歸策略模式

#include "ICameraRender.h" 

class Camera{ 
private: 
    ICameraRender*  _cameraRender; 

public: 
    Camera(); 
    Camera(ICameraRender& cameraRender); 
    ~Camera(); 

    void renderCamera(){ _cameraRender->render(this); } 


    void setCameraRender(ICameraRender& cameraRender); 
     /..../ 

}; 


class ICameraRender{ 
public: 
    virtual ~ICameraRender(){ 

    } 

    //Override me 
    virtual void render(Camera* camera) = 0; 
}; 

這似乎並不成爲一個優雅的解決方案,由於責任到infity環路(在ICameraRenderrender-function調用camera->renderCamera())。有沒有更好的解決這個問題?

問候

編輯:

我想出了另一種解決方案。由於對攝像機數據進行操作的功能只需要訪問數據,因此我認爲我可以將攝像機類本身分開。一個名爲Camera和CameraModel的類。最後一個包含所有需要的數據,第一個對其進行操作。 因此,我只需要一個指針CameraModel傳遞給我的功能:

class CameraModel{ 
private: 
    /...data.../ 
public: 
    /...setter and getter.../ 
}; 

class Camera{ 
private: 
    CameraModel* _cameraModel; 
    ICameraRender* _cameraRender; 

public: 
Camera(); 
    Camera(ICameraRender& cameraRender); 
    ~Camera(); 

    void renderCamera(){ _cameraRender->render(_cameraModel); } 

    void setCameraRender(ICameraRender& cameraRender); 
     /..../ 
}; 

class ICameraRender{ 
public: 
    virtual ~ICameraRender(){ 

    } 

    //Override me 
    virtual void render(CameraModel* cameraModel) = 0; 
}; 

現在渲染功能(只根據用戶輸入的計算相機新值)也不再有機會獲得renderCamera-功能。 您對這個解決方案有什麼看法?

問候斯坦

+0

將攝像頭用作渲染器使用的某些東西會更有意義,而不是相反。也就是說,渲染器被賦予一個或多個攝像機,其視角必須根據攝像機的狀態呈現。你確定你正在以正確的方式去做嗎? –

+0

這正是我想要做的。我想我爲這些功能選擇了錯誤的名稱。 :) 相機得到一些輸入,因此它應該計算新的位置和旋轉等。實際的渲染器可以通過getter方法訪問這些數據。 – Stan

回答

3

你說得對,它似乎是一個不好的設計。 :)

我不明白爲什麼相機渲染需要訪問相機。我相信你可以傳遞其他參數。渲染器不需要訪問所有攝像機成員,所以你可以傳遞它所需要的渲染(如果有很多渲染器,將它們包裝在結構體CameraConfig或類似的東西中)。

如果不同的渲染需要不同的參數,可以使用ICameraConfig作爲單獨的層次結構。

+0

在我的新解決方案中,我跟蹤了一下CameraConfig結構的方法。 :) 謝謝! – Stan

2

這可能是使用基於策略的設計來實現策略模式的好時機,尤其是因爲您使用的是C++,而且您可能針對的是早於2002的編譯器。(由於C++的模板機制非常棒,我們可以通過這種方式免費獲得戰略模式!)

首先:讓您的課程在模板參數中接受策略/策略類(在本例中爲您的ICameraRenderer)。然後,指定您正在使用該模板參數中的某個方法。撥打相機類中的該方法的電話...

然後使用render()方法將您的策略​​實現爲普通的舊類!

這將是這個樣子:

class Camera<RenderStrategy>{ 
    using RenderStrategy::render; 

    /// bla bla bla 

    public: 
     void renderCamera(){ render(cameraModel); } 
}; 

class SpiffyRender{ 
    public: 
     void render(CameraModel orWhateverTheParameterIs){ // some implementation goes somewhere } 
}; 

每當你想使用這些策略/戰略的一個攝像頭:

// the syntax will be a bit different, my C++ chops are rusty; 
// in general: you'll construct a camera object, passing in the strategy to the template parameter 
auto SpiffyCamera = new Camera<SpiffyRender>(); 

(因爲你的渲染策略沒有任何狀態,這使得這種方法更加有利)

如果你一直在改變你的渲染器,那麼這種模式/方法變得不那麼有利......但是如果你有相機總是呈現相同的方式,這是一個稍微好一些的方法。如果你的渲染器有狀態,你仍然可以使用這種方法;但是您需要在類中引用實例,並且不會使用Using ::語句。 (一般來說,這一點,你少寫樣板,並不需要做在運行時的任何分配或分配,以及編譯器爲你的作品)

想了解更多,請參閱:http://en.wikipedia.org/wiki/Policy-based_design 或閱讀現代C++設計...這是一個偉大的閱讀,反正! http://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315

作爲一個不相干的人:你可能想看看C++ x11給你的一些好處。它會真正清理你的代碼並使其更安全。 (特別是共享/唯一/ etc ptr類)