I have an enumeration with the commands Play
, Stop
and Pause
for a media player. In two classes I do a switch-case over the received commands. The player runs in a different thread and I deliver the commands in a command queue to the thread.
If I generate class diagrams the enumeration has dependencies all over the place. Is there a nicer way to deal with the commands? If I would change/extend the enumeration, I would have to change several classes. (Its not super important to keep the player extensible, but I try to write nice software.)
2
A “nicer” way is to have three methods, one per command.
There is no need to collapse all those commands into one method and to use a switch later. Since those commands do different things, they deserve their own methods in the interface.
Instead of:
public void ChangeState(PlayerState newState)
{
switch (newState)
{
case PlayerState.Play:
// Start playing.
case PlayerState.Stop:
// Stop playing.
case PlayerState.Pause:
// Pause or resume.
}
}
you would have:
public void Play()
{
// Start playing.
}
public void Stop()
{
// Stop playing.
}
public void Pause()
{
// Pause or resume.
}
Why?
Your current implementation using a switch will:
- either do multiple things,
- or will just serve to call
Play
,Stop
andPause
methods.
In the first case, you break the rule which says that a method should do one and one only thing.
In the second case, KISS: don’t write a method you really don’t need and which doesn’t bring anything useful to the API.
What you seem to be doing is taking 3 separate inputs, merging them into a single variable, and passing that along to be processed. Your processing code then does a switch / if statements on this variable.
As MainMa mentioned, the obvious and cleaner approach would be to simply have 3 methods, and have your interface call those. If, for some reason, you wish to have a slightly more disconnected model (say, if you need to execute the command at a later stage then when it’s triggered), the typical way is the Command Pattern where you effectively encapsulate a method call in an object (which can be serialised / stored / sent over the network / run multiple times, etc). The advantage over your enum is that it caters for input parameters (e.g. if you have a volume control command). That said, this is an unneccessary over-complication, and I’d stick to plain old methods.
5