Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OOP design - many objects each with unique interactions to limited subset of others

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.

like image 319
Michael Parker Avatar asked Mar 06 '13 17:03

Michael Parker


3 Answers

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.

like image 106
juco Avatar answered Oct 09 '22 15:10

juco


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

like image 26
Ray Tayek Avatar answered Oct 09 '22 13:10

Ray Tayek


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();
    }
}
like image 27
Garrett Hall Avatar answered Oct 09 '22 13:10

Garrett Hall