Jump to content
  • Advertisement
povilaslt2

Question about Observer pattern

Recommended Posts

Hello, I have a question about Observer pattern. I have Application class that has lists of objects, enemies and etc and I want to notify Observer when enemies list JUST got empty. How do I do that? Do I extend std::vector's erase function?

Application has render method that draws and updates application. Also this method deletes items from vectors if they are dead or etc.

Edited by povilaslt2

Share this post


Link to post
Share on other sites
Advertisement

I mean I don't want to put this code in render function. I want to do like callback or etc.

Now I added std::function(lamda) as OnDeath function to every enemy and call it at destructor. Function is checking if enemy list has 1 item in it and then call what I need.

Just IDK if it's correct usage.

Edited by povilaslt2

Share this post


Link to post
Share on other sites
5 hours ago, povilaslt2 said:

How do I do that? Do I extend std::vector's erase function?

Can't do that. Wrap a class around it that forwards all vector calls to the real vector, and extend the erase method.

Share this post


Link to post
Share on other sites

Oxyd's answer is the best.

This is why it is important to have setters and getters for your class member variables. If the only way the Lists can be modified is through a setter or getter (or, more to the point a 'removeEntity' method) then you can easily wrap other behaviour into the event that an object is erased.

Share this post


Link to post
Share on other sites
7 hours ago, Guy Thomas said:

Oxyd's answer is the best.

This is why it is important to have setters and getters for your class member variables. If the only way the Lists can be modified is through a setter or getter (or, more to the point a 'removeEntity' method) then you can easily wrap other behaviour into the event that an object is erased.

This has nothing to do with writing getters and setters (which are evil and should be avoided). It's actually about exposing the correct semantic interface to a class's consumers - encapsulation and abstraction.

Share this post


Link to post
Share on other sites

A little clarity on that...

Think about your actual interface.  Do you really need accessors and mutators (or under different names, getters and setters)? Don't provide wrappers only for the sake of being a wrapper.  Wrappers have an overhead cost; some languages can potentially remove or reduce that cost at compilation as an optimization, others can remove or reduce the cost as a JIT operation, but you shouldn't do it unless there is a reason for doing it.

Your class should do something, it should have a responsibility. That purpose shouldn't be to be the same as a standard library class because then you're just duplicating existing functionality.

Design the interface of your class with that responsibility in mind.  If the responsibility can be implemented with a one-line accessor or mutator, then do so. But don't provide accessors and mutators as a matter of course or habit; ensure there is a reason your interface should include them.

On 8/5/2017 at 5:49 AM, povilaslt2 said:

Do I extend std::vector's erase function?

No.  Extending a standard library containers is the wrong approach.  

C++ has many features for your own safety, but there are many rules you are expected to know and follow. Notice the std::vector class does not have a virtual destructor. In C++, having a non-virtual destructor is a big warning sign that you shouldn't derive from that class.  The compiler won't enforce it through a compile-time error because there are a few situations where it is legal and necessary, but this is not one of those times. All it takes is a single dynamic allocation and the program will suffer from undefined behavior, resource leaks, and similar problems.

 

Chances are good that while your system is using a container type, that container has different responsibilities from a std::vector.  The container might use a std::vector internally, but it should not be completely replaceable by a vector either. Consequently, inheritance is not the answer.  Compose your container so that it makes use of a std::vector or some other container internally.  Then add functions to add or remove event listeners as part of your container's interface.

Share this post


Link to post
Share on other sites

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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!