macco macco - 3 months ago 12
C++ Question

Middleman object for access management?

I have two classes:

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();
}


Now I want
GameObject
to be able to call
getGameObjectsAt
and
addObject
from
World
in its
update
function. However I don't want
GameObject
to be able to call the
update
function of
World
.




I could make a new class
WorldSomething
that contains my
World
object and has the functions
addObject
and
getGameObjectsAt
. I could then pass my
WorldSomething
object to the
GameObject
update function:

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);
}


However this moves my operations further away from my data, and I have to pass my WorldSomething object to the update function of GameObject. Is there a better solution? (I'm using c++ if that helps...) Also what would you call such a
WorldSomething
class?

Answer

However this moves my operations further away from my data ...

That's actually desired.


Use interfaces in 1st place to decouple logic and data:

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() {}
};

Add a strategy that provides the logic

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_;
};

This is a rough sketch, hope you get the idea.