簡體   English   中英

如何在不同情況下使用不同的子類?

[英]How can I use different subclass in different situation?

我有這樣的困境:

我有一個父類MediaPlayer ,然后從它繼承了一些子類,假設它們是MediaPlayerSub1 MediaPlayerSub2 MediaPlayerSub3 ,它們都擴展了一些不同的方法。

在我的客戶端中,我想在不同的情況下使用不同的子類,因此遇到了很多困難:當我使用MediaPlayer我總是需要判斷它是哪個子類,例如:

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
}

我是否有更好的選擇來重構代碼以減少耦合?

如果您是MediaPlayer的作者,則可以在MediaPlayer中編寫一個抽象方法

abstract void action();

並在每個子類中覆蓋它,如下所示:

@Override
void action() {
   // do something
}

然后,您只需要調用mMediaPlayer.action()

如果您不是MediaPlayer的作者,則可以執行相同的操作,但可以使用包裝器類,如下所示

abstract class MediaPlayerWrapper {

    private final MediaPlayer mediaPlayer;

    MediaPlayerWrapper(MediaPlayer mediaPlayer) {
       this.mediaPlayer = mediaPlayer;
    }

    MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    abstract void action();
}

然后,為MediaPlayer的每個子類創建子類。 像這樣:

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

然后,您只需要使用MediaPlayerWrapper而不是MediaPlayer

解決方案是使用著名的FACTORY模式進行重構。

簡而言之,工廠模式是一種創建模式,您可以在其中基於Input動態加載類。 客戶端沒有關於實現或子類的任何信息。

在您的情況下,上面發布的代碼是客戶端,理想情況下,它應該不知道子類。 而是應該知道有一個Factory類負責向客戶提供所需的子類。

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

您可能看起來很繞道,但是想法是客戶不應該知道子類及其松散耦合的種類,從而使代碼更具模塊化。 希望這回答了您的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM