0

I have an OOP design question (I am using java but the question is more general). I am programming home automation simulator and I have some trouble designing it. There's a class for each appliance, like Television or Heating with corresponding methods like volumeUp(), ... I would like decouple classes for appliances and sensors which are generating events and executing actions on them. I could think of this: I'll implement observer pattern to propagate events from sensors to alarm classes. Alarm class looks like this:

class Alarm implements Observer {
    Action action;
    public update(...) { action.do() }
}

Now, since I want to let the user to be able to arbitrarily couple sensors and actions they trigger in user interface I've thought of creating separate class for each action on each appliance

class ActionTVVolumeUp implements Action {
    Television tv;
    ActionTVVolumeUp(Television tv) { this.tv = tv; }
    public void do() { tv.volumeUp() }
}

and then when user specifies sensor (MotionSensor,LightSensor,...) in user interface and action to trigger I'll create Alarm instance with desired action observing desired sensor. The problem with this is that I am going to need many and many action classes (possibly reducing them a bit by using interfaces like VolumeControllable which appliances would implement).

Is there something I am missing and could this be done simpler/without need to use so many Action classes? Thank you.

icktoofay
  • 126,289
  • 21
  • 250
  • 231
user2079392
  • 167
  • 7

2 Answers2

0

How about the following: each appliance provides a lookup of the actions it can perform, eg a dictionary that maps a human readable name to a method. Each sensor has a list of actions (methods) it should call when triggered. The UI just adds methods to the sensor.

In C# the sensor's list of methods would be an event handler, and appliance methods would be some sort of delegate. Then in the UI, the code to hook an appliance action to a sensor is just aSensor.actions += anAppliance.aMethod; I don't remember if/how this translates into Java but I'm sure there's a way - maybe someone else can help there.

FusterCluck
  • 493
  • 1
  • 6
  • 19
  • Thank you for your answer. I did a bit of reading and I could do this in java using command pattern (which is basically what I said before) or using java reflections. This question is related http://stackoverflow.com/questions/4685563/how-to-pass-a-function-as-a-parameter-in-java – user2079392 Mar 27 '13 at 19:10
  • The command pattern seems about right. But you don't need separate classes that implement Action for each action, which was the whole point if I read your post correctly. – FusterCluck Mar 27 '13 at 19:29
  • The disadvantage of this solution is I cannot create complex actions based on state of more sensors. Also I kind of don't like the solution where methods would be called directly by sensor, seems to me that just sending event to other component that would handle actions is more clear (and closer to how would hardware sensor work) but I can't come up with argument of why it's bad so it's probably just a predujice. Thank you. – user2079392 Mar 27 '13 at 19:38
0

How about a generic pub-sub controller to implement a generic event handler? Instead of a TV device, you'd create an Appliance instance with the name of TV. In each appliance you'd add commands appropriate to that specific appliance. And no command would ever talk to another appliance, it would always talk to the controller. That way the controller maintain a copy of all the state for all the appliances, and it would know whenever a change is made, and would also know when a change needs to be made.

This way your controller could handle rules (or you could even plug a rule-appliance into the controller. It could watch for "IF living-room-tv is turned-on-event AND motion-detector-living-room was active in the last 60 seconds THEN execute dim-the-living-room-lights scenario"

Obviously there would be a problem when the appliance wants to control itself (if you hit the Channel Up button on the TV, how does the controller know?) But otherwise, as long as the TV doesn't dim the lights itself, the controller will always be in the right state to let the rules do the right thing.

If you can avoid embedding the specific appliance activities in a class, and instead generically handle names tied to executable actions, it should be forever flexible.

John Deters
  • 4,295
  • 25
  • 41