Sign in to follow this  

The Observer Pattern

This topic is 3629 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to implement the Observer pattern and run into some problems right away. I'll start with this problem but I'm sure I'll run into more later on which I'll post here too ^^. I'm planning on using this for a simple (but as complete as possible) Pong clone. First I tried implementing it in the most simple way I thought possible:
#include <iostream>
#include <list>

using namespace std;

class ISubject;

class IObserver {
  public:
    virtual void Update(ISubject*);
};

class ISubject {
  public:
    virtual void Register(IObserver* o) { observerList.push_back(o); }
    virtual void Notify(void);
  private:
    list<IObserver*> observerList;
};

void ISubject::Notify(void) {
  for (list<IObserver*>::const_iterator i = observerList.begin();
       i != observerList.end(); i++)
  {
    (*i)->Update(this);
  }
}

class Paddle : public ISubject {
  public:
    void MoveTo(int x, int y) { xPos = x; yPos = y; Notify(); }
  private:
    int xPos, yPos;
};

class Renderer : public IObserver {
  public:
    void Update(ISubject*);
};

void Renderer::Update(ISubject* s) {
  cout << "Received notification from a subject!" << endl;
};

int main()
{
  Paddle   myPaddle;
  Renderer myRenderer;
  
  myPaddle.Register(&myRenderer);
  myPaddle.MoveTo(10, 10);
  
  cin.get();
  
  return 0;
}

But I receive the following error:
Quote:
[Linker error] undefined reference to `vtable for IObserver'
I've never really seen an error like this before and have no idea what it means and what to do with it. Anyone around that does ^^? Thank you in advance.

Share this post


Link to post
Share on other sites
Quote:
Original post by Arjan B
I'm trying to implement the Observer pattern... I'm planning on using this for a simple (but as complete as possible) Pong clone.


I don't see how. This is almost certainly design overkill. What are you going to use it for?

Quote:
But I receive the following error:
Quote:
[Linker error] undefined reference to `vtable for IObserver'


Explanation.

In your case, it can't find the definition of the function IObserver::Update, because there isn't one. You need to indicate that this is deliberate, by using a pure virtual function:


class IObserver {
public:
virtual void Update(ISubject*) = 0;
};


Yes, it's quite strange syntax. Strange historical reasons for it. Sorry.

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
I don't see how. This is almost certainly design overkill. What are you going to use it for?
Err.. I think this is my fault. In his other thread about decoupling graphics from game code, I suggested using events for the different modules to communicate and mentioned that in my own project I was using the Observer pattern to pass events (more or less)...


Arjan B:
Even though it is overkill for what you are doing, you already have most of the code written, so I suggest use it anyway as a learning experience. If anything, it will help you with your next game.
Other people may hit me for this .

Share this post


Link to post
Share on other sites
Thanks, declaring it as a pure virtual function solved it ^^. Like issch just said, I already have created a simple Pong clone but it had no menu's or other states or whatever and was designed in a way that it was hard to add new stuff to it ^^.

The Observer pattern seems nice to me since it keeps things seperated and when I'm done I could, for example, implement a 3d view without redesigning the whole game.



Now for some other questions ^^:
Can a class be a subject as well as an observer? The paddle needs te be observed by the renderer but doesn't the paddle also need to be observing the input?

And let's say the paddle object moves, so I notify the renderer. Should I pass Notify() something like an enum of events (EVENT_MOVE) and some extra parameters to say where to? Something like Notify(event e, int param1, int param2) seems ok to me since I won't be notifying about much else than movement. But I might be all wrong about this ^^.

And where does the renderer keep this information? If the paddle doesn't move for a few screens but the screen needs to be updated for the moving ball for example, it still should know about where to draw the paddle.

Share this post


Link to post
Share on other sites
Quote:
Original post by Arjan B
Can a class be a subject as well as an observer? The paddle needs to be observed by the renderer but doesn't the paddle also need to be observing the input?
Well, yes. In my game every game object (for want of a better term, im including the renderer and input system in my definition of object) can generate and listen for events. Like I said in the other thread, I don't use the observer pattern as is, I modified it a little. Having said that, you do not need to, you could use multiple inheritance to derive from both of your IObserver and ISubject classes.

Quote:

And let's say the paddle object moves, so I notify the renderer. Should I pass Notify() something like an enum of events (EVENT_MOVE) and some extra parameters to say where to? Something like Notify(event e, int param1, int param2) seems ok to me since I won't be notifying about much else than movement. But I might be all wrong about this ^^.
Yes, you will need to give it some sort of information. In my game code, I have an Event class from which events are derived. Each type of event has fields describing the events. You could do something similar and pass an event to your notify method.

Quote:

And where does the renderer keep this information? If the paddle doesn't move for a few screens but the screen needs to be updated for the moving ball for example, it still should know about where to draw the paddle.
Again, I'm just telling you how I am doing things. This is by no means the best way, but hopefully will give you some ideas. My renderer has a list of graphical objects that it renders each frame. They only contain graphical information, such as where on screen they should be drawn, what texture, colors, whatever. The game objects contain only non-graphical information used by the gameplay and physics code. So when a game object moves (for example), it dispatches an event, which the renderer receives. The renderer uses the information contained in the event to update it's graphical objects (by moving the matching graphical object to it's new location on the screen).
That is, the renderer contains state information and uses the events to update the state information.

Hope that helps.

Share this post


Link to post
Share on other sites

This topic is 3629 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this