簡體   English   中英

這是適配器模式的正確實現嗎?

[英]Is this a correct implementation of an adapter pattern?

所以我有兩個類:SoccerPlayer和IceHockeyPlayer
它們都有一些方法自己的接口:ISoccerPlayer和IIceHockeyPlayer

足球運動員:

public class SoccerPlayer implements ISoccerPlayer {

    public String[] teammembers;

    @Override
    public void kickFootball(int meters) {
        // Kick the football
    }

    @Override
    public void runForward(double speed) {
        // Run forward
    }

    @Override
    public void addTeammembers(String[] memberNames) {
        // Add the members
    }
}    

IceHockeyPlayer:

public class IceHockeyPlayer implements IIceHockeyPlayer {

    public ArrayList<String> teammembers;

    @Override
    public void hitPuck(int meters) {
        // Hit the puck
    }

    @Override
    public void skateForward(double speed) {
        // Skate forward
    }

    @Override
    public void addTeammembers(ArrayList<String> memberNames) {
        // Add the members
    }

}  

接下來,我創建了一個同時包含SoccerPlayer和IceHockeyPlayer的類,該類同時實現了這兩個接口,這將是我的適配器。
此類中的方法僅調用SoccerPlayer或IceHockeyPlayer的正確方法:

public class Adapter implements ISoccerPlayer, IIceHockeyPlayer {

    public SoccerPlayer soccerplayer;
    public IceHockeyPlayer icehockeyplayer;

    public Adapter(SoccerPlayer soccerplayer, IceHockeyPlayer icehockeyplayer) {
        this.soccerplayer = soccerplayer;
        this.icehockeyplayer = icehockeyplayer;
    }

    // SoccerPlayer
    @Override
    public void kickFootball(int meters) {
        this.soccerplayer.kickFootball(meters);
    }

    @Override
    public void runForward(double speed) {
        this.soccerplayer.runForward(speed);
    }

    @Override
    public void addTeammembers(String[] memberNames) {
        this.soccerplayer.addTeammembers(memberNames);
    }

    // IceHockeyPlayer
    @Override
    public void hitPuck(int meters) {
        this.icehockeyplayer.hitPuck(meters);
    }

    @Override
    public void skateForward(double speed) {
        this.icehockeyplayer.skateForward(speed);
    }

    @Override
    public void addTeammembers(ArrayList<String> memberNames) {
        this.icehockeyplayer.addTeammembers(memberNames);
    }

}  

這是適配器模式的正確實現嗎? 如果沒有,我需要做些什么改變使其成為一體?

那更像是門面。

對於適配器,您會遇到類似

interface SportsPlayer {
    public void play(int meters);
    public void move(double speed);
}

和類似的適配器

class IceHockeyPlayerAdapter implements SportsPlayer {
    private IceHockeyPlayer player;
    public IceHockeyPlayerAdapter(IceHockeyPlayer p) { player = p; }

    public void play(int meters) {
        player.playPuck(meters);
    }
    public void move(double speed) {
        player.skateForward(speed);
    }
}

它將“適應”冰球運動員“變成” SportsPlayer 因此實際上是另一種方法集。

編輯:

這是真正的JDK的適配器用法。

您知道可以使用try-with-resources來自動關閉資源,並且可以在提交任務后關閉ExecutorService 好吧,“嘗試資源”需要一個AutoCloseable ,而ExecutorService卻沒有實現。 救援工具:

public class AutocloseableExecutorService implements ExecutorService, AutoCloseable {
    private ExecutorService delegate;
    public AutocloseableExecutorService(ExecutorService d) {
        delegate = d;
    }
    // delegate ExecutorService methods to implement the interface
    public void execute(Runnable r) { delegate.execute(r); 
    // ...

    // implement close() for AutoCloseable
    public void close() {
        delegate.shutdown();
    }
}

所以現在您可以像這樣使用它:

public void submitTasks(Runnable... rs) {
    try (AutocloseableExecutorService executor = new AutocloseableExecutorService(
             Executors.newSingleThreadExecutor())) {
        for (Runnable r : rs) executor.submit();
    }
}

該方法結束時,該服務將被注冊為關閉。

嚴格來講,這不是適配器。
您可以使用由2個接口組成的對象的組合:

public class Adapter implements ISoccerPlayer, IIceHockeyPlayer 

GOF適配器模式通常將一個對象(但可能是多個)適應一個特定的接口 ,以便允許客戶端操縱接口類型,而適配器中使用的適應對象可能不提供該對象所需的方法。客戶端界面。

例如,使用以下客戶端界面:

interface SportPlayer {
    void play();
}

假設SoccerPlayer沒有play()方法,而是功能上等效的方法,其名稱為playSoccer()
為了使SoccerPlayer對象適應SportPlayer您可以創建一個SoccerAdapter

public class SoccerAdapter implements SportPlayer {
   private SoccerPlayer soccerPlayer;

   public SoccerAdapter(SoccerPlayer soccerPlayer){
      this.soccerPlayer = soccerPlayer;          
   }
   public void play(){
        soccerPlayer.playSoccer();
   }
} 

不,那不是適配器模式。 您使用適配器將呼叫者期望的行為/方法映射到提供者提供的行為。

例:

假設您要構建一個可以處理玩家的機器人。 它只是知道一個播放器看起來像這個界面(我重用您的示例,不管這個有意義與否超出此問題的范圍):

interface Player {
  void shoot(int meters);
  void move(double speed);
  addTeammembers(ArrayList<String> memberNames);
}

該接口的適配器如下所示:

class SoccerPlayerAdapter implements Player {
  SoccerPlayer soccerplayer; //set via constructor

  void shoot(int meters) {
    soccerplayer.kickFootball(meters);
  }

  void move(double speed){
    soccerplayer.runForward(speed);
  }

  addTeammembers(ArrayList<String> memberNames) {
    soccerplayer.addTeammembers(memberNames);
  }
}

正如你所看到的SoccerPlayerAdapter “適應” SoccerPlayerPlayer ,即它映射的方法shoot(int meters)kickFootball(int meters)等。

注意:如果接口不能直接實現,或者由於其他原因這樣做沒有多大意義,那么通常使用適配器。 在您的示例(也是我的示例)中,讓玩家直接實現Player界面並將kickFootball(meters)重構為更通用的方法kickFootball(meters) shoot(meters)等會更有意義。

適配器模式解決了以下問題:存在現有的Consumer代碼和現有的Producer代碼,並且Consumer代碼的accet類型與Producer代碼產生的類型不兼容

[ Consumer代碼和Producer代碼不是標准術語,我更喜歡使用它們來使我的觀點易於理解]

為了解決此問題,我們創建了一個單獨的Adapter代碼,該代碼使用Producer代碼中的生產類型並將其轉換Consumer代碼使用的類型。

 Consumer ---consume (TypeX) //accepts TypeX, Existing code
 Producer   ----produce () : TypeY //returns TypeY, Existing code
 Adapter     ---- adapt(TypeY) : TypeX //New code to work with two existing code.accepts TypeY adapts it to TypeX and returns the same.

對於代碼,您可以參考(易於理解) https://www.geeksforgeeks.org/adapter-pattern/

暫無
暫無

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

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