In the game I'm developing I need to determine if an action is possible. Whether the action is possible is dependent on a number of factors spread across many objects (ActionDeterminers) in the game. These objects may or may not exist, and whether each of the objects allows the action is dynamic.

I had the idea to implement an Observer-style pattern, where these ActionDeterminers can register themselves with a Subject. When the Subject is asked IsActionPossibleEverywhere, it can then call an interface function on each of the ActionDeterminers: IsActionPossible, and then AND all of their results. Is there a name for this pattern?

The issue I'm facing is that I would also like to notify another set of objects (Observers) of changes in the result of IsActionPossibleEverywhere, using the standard Observer pattern. As far as I can tell, I have two options for this:

  1. Polling. I could simply call IsActionPossibleEverywhere in the main loop, and then notify every Observer when the the result changes from the last call. Unfortunately, the IsActionPossibleEverywhere call could potentially be non-performant (depending on each of the ActionDeterminers).

  2. Give each of the ActionDeterminers the additional responsibility of informing the Subject of when their personal IsActionPossible call might change. The Subject will then call IsActionPossibleEverywhere and inform its Observers if the result changed from the last call. This is considerably more complex and has more potential points of failure.

New contributor
jeevcat is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
  • If I understood you correctly, your ActionDeterminers calculate IsActionPossible on-the-fly, but you only really use the final combined value? Regardless, if it's a game, you have a game loop. Can you, at some point in the update cycle, compute the value and store the result for the duration of that iteration? And then subsequently ask for it (the cached one) wherever you need it? You may need to pass it along, maybe within a context object, or something like that, unless your Subject is otherwise accessible. – Filip Milovanović yesterday
  • @FilipMilovanović yes you've understood correctly. The method you describe is probably my best option. The Subject is accessible so that shouldn't be a problem. I also want an event to fire, but I can do that if I compare to the cached value on computation. Only issue is if the computation is too expensive to run every cycle of the game loop. – jeevcat yesterday
  • Unless it's something that obviously takes a long time, you won't really know if it's expensive until you test it. That said, if it does turn out to be time consuming, and you cannot improve or simplify the algorithm, there are some tricks you can try. If it's a continuous thing, you can skip some cycles (e.g., people sometimes update AI only every second frame). On the other hand, If you want something like an event, you can just set a flag, then check it (and unset it) when the time comes to compute IsActionPossibleEverywhere (this may happen on the next frame, but that may be OK). – Filip Milovanović yesterday

I would suggest the "querying-on-demand" approach. Polling on the main loop is essentially the traditional approach, killing the event-driven approach that makes the Observer pattern so important.

As you have a number of arbitrary objects, with no structure known beforehand, and complex collaborations between them, I suggest you take a look at the Mediator design pattern. You can still use the Observer pattern to join/detach them to the collaboration.

  • But how do I notify the 2nd set of objects (Observers in my question) when the result of the IsActionPossibleAnywhere query changes? – jeevcat 2 days ago
  • Is it really necessary? Just requesting the overall result only when needed should be enough. You mentioned that the cost of asking may be too high on certain cases, so instead, I would consider "caching" locally as much data as possible, so doing the final computation of IsActionPossible is not as expensive. I don't know if this makes sense in your particular context... – Jesus Alonso Abad 2 days ago
  • I need to hide and show a UI element based on the outcome. It seems I'll have to poll the overall result every frame. I should be able to cache for the case where I perform multiple requests each frame. Otherwise, I need some kind of event informing that the UI should change. – jeevcat 2 days ago

Your Answer

jeevcat is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.