我正在用C ++创建一个小型模拟框架。我想将纯模拟相关的东西与显示分开。所以我有类似的课程:
class Pointer : public SimulationObject {};
class Particle : public SimulationObject {};
class LearningObserver : public SimulationObject {};
这些都是从SimulationObject派生的,但只有一些(!)具有可视化表示:
class Renderable {
public:
virtual void render() const = 0;
//may also include reference to assosciated SimulationObject
}
class PointerRenderable : public Renderable {
void render() const { std::cout << "Render a pointer" << std::endl;
};
class ParticleRenderable : public Renderable {
void render() const { std::cout << "Render a particle" << std::endl;
};
现在,无论何时将新的SimulationObject添加到我的Simulation(运行时),我都要检查是否存在渲染它的类。如果是这样,我想创建它的一个实例。我的第一个想法是使用多态:
class AbstractRenderFactory {
virtual Renderable * provideRenderable(SimulationObject * so) const = 0;
};
class ConcreteRenderFactory {
void PointerRenderable * provideRenderable(Pointer * pointer) {
return new PointerRenderable();
}
// further provideRenderable's
};
但是,当重写方法时,使用派生类型显然不起作用(调用基本方法)。这也是有问题的,因为只能部分定义函数。
另一个想法是提供类型的实际映射:
std::map<std::type_index, std::type_index> renderTable;
但是我只能使用type_info来获取实例。你有什么想法吗?
更新:我尝试使用访客模式,但是我遇到了类似的问题。我的访客类看起来像这样:
class RenderVisitor {
public:
virtual Renderable * visit(SimulationObject * so) {
// I would like to have this method abstract, but I could live with this
return 0;
}
};
class MyRenderVisitor : public RenderVisitor {
public:
Renderable * visit(Pointer * pointer) const {
return new PointerRenderable();
}
};
加上我的模拟部件的新基类。
class SimulationObject {
public:
Renderable * accept(RenderVisitor * renderer) {
return renderer->visit(this);
}
};
MyRenderVisitor的visit-method显然不被认为是对基类的重写,但我希望用 this 指向实际(派生)类型,正确的方法(MyRenderVisitor)将被调用。
我的测试场景如下所示:
RenderVisitor * rv = new MyRenderVisitor();
SimulationObject * pointer = new Pointer();
Renderable * renderable = pointer->accept(rv);
renderable->render();
// renderable = 0 -> seg-fault
或者只是我的实施错误了?
答案 0 :(得分:1)
是的,您似乎需要双重调度技术,可以通过应用Visitor pattern来实现。 用于说明这个想法的代码:
界面部分:
class SimulationObject {
public:
virtual void Accept(RenderableVisitor* visitor) const = 0;
...
};
class RenderableVisitor {
public:
virtual void Visit(Pointer* pointer) const = 0;
virtual void Visit(Particle* particle) const = 0;
virtual void Visit(LearningObserver* learning_observer) const = 0;
}
具体部分:
class Pointer : public SimulationObject {
public:
virtual void Accept(RenderableVisitor* visitor) const
{
visitor->Visit(this);
}
};
class Particle : public SimulationObject {
public:
virtual void Accept(RenderableVisitor* visitor) const
{
visitor->Visit(this);
}
};
class LearningObserver : public SimulationObject {
public:
virtual void Accept(RenderableVisitor* visitor) const
{
visitor->Visit(this);
}
};
class ConcreteRenderableVisitor : public RenderableVisitor {
public:
virtual void Visit(Pointer* pointer) const
{
std::cout << "Render a pointer" << std::endl;
}
virtual void Visit(Particle* particle) const
{
std::cout << "Render a particle" << std::endl;
}
virtual void Visit(LearningObserver* learning_observer) const
{
std::cout << "Render a learning observer" << std::endl;
}
}
ConcreteRenderableVisitor
类为SimulationObject
类层次结构的每个叶子实现逻辑。
客户代码:
ConcreteRenderableVisitor visitor;
Particle particle;
particle.Accept(&visitor); // Render a particle by the visitor.
客户端代码2(用于证明该技术的更抽象的示例):
RenderableVisitor* visitor = new ConcreteRenderableVisitor;
SimulationObject* object = new Particle;
object->Accept(visitor);