这是适配器模式的正确实现吗?
Is this a correct implementation of an adapter pattern?
所以我有两个 classes: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
}
}
冰球运动员:
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
}
}
接下来,我创建了一个 class,其中包含实现这两个接口的 SoccerPlayer 和 IceHockeyPlayer,这将是我的适配器。
class 中的方法只是调用 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);
}
}
曲棍球运动员 "adapt" "become" SportsPlayer
;所以它实际上是一个不同的方法集。
编辑:
下面是真正的适配器用法JDK。
您知道可以使用 try-with-resources 自动关闭资源,并且可以在提交任务后关闭 ExecutorService
s 吗?嗯,try-with-resources 需要 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 适配器模式通常将一个对象(但也可能是多个)适配到一个特定接口,以允许客户端在适配对象的同时操作接口类型(s) 适配器中使用的可能未提供客户端接口所需的方法。
例如采用此客户端界面:
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();
}
}
不,这不是适配器模式。您使用适配器将调用者期望的内容映射 behavior/methods 到提供者提供的内容。
示例:
假设您想构建一个机器人来管理您的玩家。它只知道播放器看起来像这个界面(我重用你的例子,这是否有意义不在这个问题的范围内):
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
"adapts" SoccerPlayer
到 Player
,即将方法 shoot(int meters)
映射到 kickFootball(int meters)
等。
注意:如果接口不能直接实现或者由于其他原因这样做没有多大意义,您通常会使用适配器。在您的示例(以及我的示例)中,让玩家直接实现 Player
接口并将 kickFootball(meters)
重构为更通用的方法 shoot(meters)
等会更有意义
适配器模式解决了存在现有 Consumer
代码和现有 Producer
代码并且 Consumer
之间存在 不兼容 时的问题代码访问类型和 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/
所以我有两个 classes: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
}
}
冰球运动员:
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
}
}
接下来,我创建了一个 class,其中包含实现这两个接口的 SoccerPlayer 和 IceHockeyPlayer,这将是我的适配器。
class 中的方法只是调用 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);
}
}
曲棍球运动员 "adapt" "become" SportsPlayer
;所以它实际上是一个不同的方法集。
编辑:
下面是真正的适配器用法JDK。
您知道可以使用 try-with-resources 自动关闭资源,并且可以在提交任务后关闭 ExecutorService
s 吗?嗯,try-with-resources 需要 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 适配器模式通常将一个对象(但也可能是多个)适配到一个特定接口,以允许客户端在适配对象的同时操作接口类型(s) 适配器中使用的可能未提供客户端接口所需的方法。
例如采用此客户端界面:
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();
}
}
不,这不是适配器模式。您使用适配器将调用者期望的内容映射 behavior/methods 到提供者提供的内容。
示例:
假设您想构建一个机器人来管理您的玩家。它只知道播放器看起来像这个界面(我重用你的例子,这是否有意义不在这个问题的范围内):
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
"adapts" SoccerPlayer
到 Player
,即将方法 shoot(int meters)
映射到 kickFootball(int meters)
等。
注意:如果接口不能直接实现或者由于其他原因这样做没有多大意义,您通常会使用适配器。在您的示例(以及我的示例)中,让玩家直接实现 Player
接口并将 kickFootball(meters)
重构为更通用的方法 shoot(meters)
等会更有意义
适配器模式解决了存在现有 Consumer
代码和现有 Producer
代码并且 Consumer
之间存在 不兼容 时的问题代码访问类型和 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/