递归策略模式

时间:2012-09-28 08:25:02

标签: c++ oop design-patterns strategy-pattern

我正在为C++中的项目设计一些课程,但我遇到了问题。 我想创建一个camera类,它包含所有需要的值(例如转换矩阵),但呈现camera的函数应该是可交换的。这听起来像战略模式的通常情况。因此,我创建了一个定义render-function的接口,并为此接口提供了camerapointer。 问题是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循环(在camera->renderCamera()中的render-function中调用ICameraRender)的责任,这似乎不是一个优雅的解决方案。这个问题有更好的解决方案吗?

此致

编辑:

我提出了另一个解决方案。由于操作相机数据的功能,只需要访问我认为可以拆分相机类本身的数据。一个名为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功能。 您对此解决方案有何看法?

问候斯坦

2 个答案:

答案 0 :(得分:3)

你是对的,看起来确实是一个糟糕的设计。 :)

我不明白为什么相机渲染需要访问相机。我相信你可以传递其他东西作为参数。渲染不需要访问所有摄像机成员,因此您可以传递它所需的那些(并且,如果有很多它们,将它们包装在结构CameraConfig或类似的东西中)。

如果不同的渲染需要不同的参数,您可以使用ICameraConfig创建单独的层次结构。

答案 1 :(得分: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为您提供的一些优点。它会真正清理你的代码并使其更安全。 (特别是shared / unique / etc ptr类。)