2016-09-02 4 views
1

У меня есть два класса:Объект Middleman для управления доступом?

class World { 
public: 
     void update(); 
     void addObject(GameObject* obj); 
     std::vector<GameObject const*> getGameObjectsAt(float x,float y,float radius) const; 
private: 
     std::vector<GameObject*> gameObjects 
} 

class GameObject { 
public: 
    void update(); 
} 

Теперь я хочу GameObject быть в состоянии назвать getGameObjectsAt и addObject из World в update функции. Однако я не хочу, чтобы GameObject мог позвонить функции updateWorld.


Я мог бы сделать новый класс WorldSomething, содержащие мой World объект и имеет функцию addObject и getGameObjectsAt. Тогда я мог бы передать мой WorldSomething объект функции GameObject обновления:

class World { 
    public: 
     void update(); 
    private: 
     std::vector<GameObject*> gameObjects 
} 



class WorldSomething { 
    public: 
     void addObject(GameObject* obj); 
     std::vector<GameObject const*> getGameObjectsAt(float x,float y,float  radius) const; 
    private: 
     World* world; 
} 

class GameObject { 
    public: 
    void update(const WorldSomething& worldSomething); 
} 

Однако это перемещает свои операции дальше от моих данных, и я должен передать свой объект WorldSomething к функции обновлени GameObject. Есть ли лучшее решение? (Я использую C++, если это помогает ...) И что бы вы назвали таким классом WorldSomething?

+0

Сделать «частных» членов «частными»? –

+0

@JoachimPileborg: update() of World должен быть общедоступным, так как он вызывается из другой части моего кода. (мой игровой цикл) – macco

+0

Можете ли вы рассказать о том, почему это проблема, если GameObject может вызвать функцию обновления World? Кроме того, если единственным объектом, которому разрешено вызывать 'update', является игровой цикл, тогда вы можете подумать о дружеских отношениях. В качестве альтернативы, шаблон посетителя, где вызывается обновление, если посетителем является gameloop, и что-то еще в противном случае. – AndyG

ответ

1

Однако это перемещает свои операции дальше от моих данных ...

Это на самом деле желаемого.


Использование интерфейсов в 1-ом месте разъединить логики и данных:

struct IWorldAdd { 
    virtual void addObject(GameObject* obj) = 0; 
    virtual std::vector<GameObject const*> getGameObjectsAt(float x,float y,float radius) 
     const = 0; 
    virtual ~IWorldAdd() {}; 
}; 

class World : public IWorldAdd{ 
public: 
    void update(); 
    void addObject(GameObject* obj); 
    std::vector<IGameObject const*> getGameObjectsAt(float x,float y,float radius) const; 
private: 
     std::vector<GameObject*> gameObjects 
}; 

struct IGameObject { 
    virtual void update() = 0; 
    virtual Point getCenterPosition() = 0; 
    virtual ~IGameObject() {} 
}; 

Добавить стратегию, которая обеспечивает логику

template<class UpdateStrategy> 
class GameObject : public IGameObject { 
public: 
    GameObject(UpdateStrategy* strategy) : strategy_(strategy) 
    void update() { 
     // Do stuff needed to update the things directly related to the 
     // GameObject's rendering and such 

     // Call the strategy needed to update a particular game object 
     // in Relation to other objects nearby 
     strategy_->updateRestOfWorld(); 
    } 
private: 
    UpdateStrategy* strategy_; 
}; 

class AConcreteUpdateStrategy { 
    AConcreteUpdateStrategy(IWorldAdd* world) : world_(world) { 
    } 

    void updateRestOfWorld(const IGameObject* gameObject) { 
     Point centerPoint gameObject->getCenterPosition(); 
     std::vector<const IGameObject*> otherGameObjects = 
      world_->getGameObjectsAt(centerPoint.x, centerPoint.x, 500); 
     // Inspect if there are specific game objects nearby 
     if(gameObjectIsNearBy) { 
       world->addObject(new OtherGameObject()); 
     } 
    } 
private: 
    IWorldAdd* world_; 
}; 

Это грубый набросок, надеюсь, вы получите идею.

+0

Спасибо. Я думаю, что создание интерфейса IWorld - довольно хорошее решение. Наличие классов стратегии добавляет слишком много сложности для того, что я пытаюсь сделать, но я могу добавить их позже, если они окажутся полезными. – macco

0

Кажется, что ваш класс отвечает за два разных аспектов. Вы видите, когда вы думаете, что часть вашего кода должна использовать только «половину» вашего класса World; то может быть, ваш Мир слишком большой?

Другими словами: было бы разумно придумать класс HalfOfTheWorld, который содержит те функции, которые нужны игровым объектам ?!

И тогда у вас может быть AnotherHalfOftheWorld, доставляющий другие аспекты; и при необходимости; ваш класс World может затем содержать один член каждого из этих новых классов.

+0

Разве это не что-то вроде _Strategy Pattern_, которое должно быть применено к «World»? –

0

Есть ли лучшее решение?

Я думаю, что лучше оставить классы как есть.

Я не вижу никакого преимущества для добавления другого слоя (или более слоев), чтобы предотвратить GameObject от возможности позвонить World::update().

Дисциплина программиста - это решение. Убедитесь, что ваш поток исполнения хорошо понятен вашим разработчикам. World::update() не будет вызываться от GameObject, если поток выполнения не требует его.