I have a dilemma like this:
I have parent class MediaPlayer
, then some subclass extends from it, let's say they are MediaPlayerSub1
MediaPlayerSub2
MediaPlayerSub3
, all of they extend some differnt methods.
In my client, I want use different subclass in different situation, so I am faced with difficulties: when I use MediaPlayer
I always need to judge which subclass it is, for example:
MediaPlayer mMediaPlayer = initPlayer()
// ... do some operation from MediaPlayer
// ... do operation from sub class
if (mMediaPlayer instanceof MediaPlayerSub1) {
mMediaPlayer = (MediaPlayerSub1)mMediaPlayer;
// ... do operation from MediaPlayerSub1
} else if (mMediaPlayer instanceof MediaPlayerSub2) {
mMediaPlayer = (MediaPlayerSub2)mMediaPlayer;
// ... do operation from MediaPlayerSub2
} else if (mMediaPlayer instanceof MediaPlayerSub3) {
mMediaPlayer = (MediaPlayerSub3)mMediaPlayer;
// ... do operation from MediaPlayerSub3
}
Do I have better choice to refactor the code to reduce the coupling?
If you are the author of MediaPlayer you can just write an abstract method in MediaPlayer
abstract void action();
and override it in each of the subclasses, like this:
@Override
void action() {
// do something
}
Then you just need to call mMediaPlayer.action()
.
If you are not the author of MediaPlayer you can do the same thing but using wrapper classes, like this
abstract class MediaPlayerWrapper {
private final MediaPlayer mediaPlayer;
MediaPlayerWrapper(MediaPlayer mediaPlayer) {
this.mediaPlayer = mediaPlayer;
}
MediaPlayer getMediaPlayer() {
return mediaPlayer;
}
abstract void action();
}
Then you create subclasses for each subclass of MediaPlayer. Like this:
final class MediaPlayerWrapper1 extends MediaPlayerWrapper {
MediaPlayerWrapper1(MediaPlayerSub1 mediaPlayer) {
super(mediaPlayer);
}
@Override
public void action() {
// do stuff with the MediaPlayer. You will need to call getMediaPlayer() first.
}
}
Then you just need to use a MediaPlayerWrapper
instead of a MediaPlayer
.