2014-02-26 37 views
4

在我的比赛,我已经定义了一个Screen类,包含了一些视觉Entity对象的引用,可以绘制到显示器:里氏替换原则和一流的设计为游戏

class Screen { 
public: 

private: 
    std::vector<Entity*> entities_; 
}; 

所有Entity的,具有Draw()功能:

class Entity { 
    public: 
    void Draw(); 
    private: 
    int xpos; 
    int ypos; 
}; 

Screen的负责调用在其每个Entity S的Draw()功能。

问题在于一些(但不是全部)Entity也需要是可更新的,即随着时间的推移它们将改变它们的外观/位置。 Screen还需要调用Update()函数,但仅适用于可更新的对象

我的问题是:

是否有意义从Entity有一个更新的功能派生类:

class ChangingEntity : public Entity { 
    public: 
    void Update(int time); 
}; 

,并有Screen是这样的:

class Screen { 
public: 

private: 
    std::vector<Entity*> entities_; 
    std::vector<ChangingEntity*> changing_entities_; 
}; 

如果我做了上述,然后我只调用Draw()为每个Entity s和Draw()Update()每个ChangingEntity s。

或者 - 我应该只把Update()函数放在Entity,如果Entity对象不能更新,那么Update()没有实现?

+3

如果您知道如何将两者静态分开,然后分开容器。多态性适用于你*不知道你将要使用的静态类型。 –

+0

你是什么意思“如果你知道如何使两者静止分开......”你的意思是如果我能明确区分它们,并且事先知道它们是什么类型?如果是这样,那么是的,我可以做到这一点。 – patchwork

+1

“从实体派生类是否有意义” - 可能目前还没有,因为“实体”不适合用作基类。它有一个公共的非虚拟析构函数,这是个坏消息。对于基类,析构函数应该是虚拟的或者是保护的。 –

回答

3

有几件事你可以在这里加强;

最好不要让实体绘制自己,使用单独的Draw()函数或Drawable类(Single Responsibility Principle)。在你目前的方法中,你正在创建任何需要绘制的类来扩展实体,下次你会发现一个类不需要是可绘制的实体。所以使用一个单独的绘图功能。

其次你应该定义什么是实体,例如Ogre3D定义Entityan instance of a discrete, movable object based on a Mesh,我没有看到你当前的定义是足够的,它只包含位置和绘图函数。您可以将实体定义为可更新对象,另一个名为StaticEntity的类不需要多态性。让场景有两个单独的列表,并且实际上能够更新对象,再将渲染器与场景分开。

您的第三个Screen类应该被称为Renderer并且具有可以根据其静态类型进行注册的对象。您也可以有一个Drawable界面。