If class A has a unique interaction with each of classes B, C and D, should the code for the interaction be in A or in B, C and D?
I am writing a little game whereby lots of objects can have unique interactions with other objects. For example, an EMP
hits a sentry gun
and disables it. It could also hit a grenade
and detonate it, it could also hit a player
and applying a slowing effect.
My question is, should this code go in the EMP class, or be spread amongst all the other classes? My gut tells me to do this polymorphically so that I simply tell each class to deal with the EMP strike however it likes, which would allow me to add more items and change how they deal with the EMP without changing the EMP code.
However, the EMP only currently interacts with about 4 out of 50 of my objects, so filling 46 objects with empty RespondToEMP() calls seems wrong. It also seems somewhat unintuitive, if I decide to remove the EMP, I need to change every other class, and the EMP class itself ends up fairly tiny. It also means if I want to change how the EMP behaves I need to go looking through all the different classes to find all the possible usages. Additionally, if the EMP has some generic effects such as an explosion, this effect would definitely be inside the EMP code, away from all the other effects which would be distributed.
My thoughts would be that sentry gun
, grenade
and player
should all be implementing a common interface that enforces the method RespondToEMP
. This way, if you later decide that one of your other 46 objects can be hit by an EMP, you'll know to implement this interface.
you may want to consider http://en.wikipedia.org/wiki/Visitor_pattern. if you have more than 2 things interacting together take a look at my answer to Managing inter-object relationships
You are right, having a dummy method is a code smell. There are a couple ways to get around this:
Switch statements to handle events works well if you expect to add more objects because you will avoid having to modify events when you add more objects:
enum Event { EMP, Bomb }
class SentryGun {
void handleEvent(Event e) { switch(e) {
case EMP: disable();
}}
void disable() {}
}
class Grenade {
void handleEvent(Event e) { switch(e) {
case EMP: detonate();
}}
void detonate() {}
}
Events that visit objects works well if you expect to add more events because you avoid having to modify every object that can now react to that event:
class EMP {
void hit(SentryGun object) {
object.disable();
}
void hit(Grenade object) {
object.detonate();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With