Search code examples
javadesign-patternsmedia-playerdecouple

How can I use different subclass in different situation?


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?


Solution

  • 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.