简体   繁体   中英

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?

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 .

The solution is to refactor using famous FACTORY pattern.

Factory pattern in short is a creational pattern where you dynamically load classes based on Input. The client has no information whatsoever on the implementation or sub classes.

In your case , the code you posted above is client and ideally it should not be aware of subclasses. Rather it should be aware of a Factory class who is responsible to provide client with desired subclass.

public enum MediaType {
   MEDIA1  ,MEDIA2 , MEDIA3, NULL ;
}

public class MediaFactory {

     public static MediaPlayer getMediaInstance(MediaType mediaType) { 
          if( mediaType == MediaType.MEDIA1) return new MediaPlayerSub1(mediaType);
          if( mediaType == MediaType.MEDIA2) return new MediaPlayerSub2(mediaType);
          if( mediaType == MediaType.MEDIA3) return new MediaPlayerSub3(mediaType);  
          return new MediaPlayer();
    }
 }
  // client code
  MediaPlayer mediaPlayer = MediaFactory.getMediaInstance(MediaType.NULL); 
  MediaPlayer mediaPlayer = MediaFactory.getMediaInstance(MediaType.MEDIA1);
  MediaPlayer mediaPlayer = MediaFactory.getMediaInstance(MediaType.MEDIA2);
  MediaPlayer mediaPlayer = MediaFactory.getMediaInstance(MediaType.MEDIA3);

  if (mediaPlayer.getMediaType() ==MediaType.MEDIA1) // do mediaSub1 operations
  if (mediaPlayer.getMediaType() ==MediaType.MEDIA2) // do mediaSub2 operations
  if (mediaPlayer.getMediaType() ==MediaType.MEDIA3) // do mediaSub3 operations

You might seem round about way, but idea is client should not know about subclasses and its kind of loose coupling, making code more modular. Hope this answered your question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM