わかりましたので、何かがエスカレートし、私は次の10クラスになりました...
このメソッドの要点は、すべての通信がMessage
クラスを使用して行われることです。つまり、ゲームはプレーヤーのメソッドを直接呼び出すことはなく、常にフレームワークのコミュニケータークラスを使用します。ネイティブJavaクラス用のリフレクションベースのコミュニケーターがあり、Java以外のすべてのプレーヤー用のカスタムコミュニケーターが必要です。Message<Integer> message = new Message<>("say", Integer.class, "Hello");
は、を返すsay
パラメータで指定されたメソッドへのメッセージを初期化します。次に、これはコミュニケーター(プレーヤーのタイプに基づくファクトリーを使用して生成)に渡され、コミュニケーターはコマンドを実行します。"Hello"
Integer
import java.util.Optional;
public class Game {
Player player; // In reality you'd have a list here
public Game() {
System.out.println("Game starts");
player = new PlayerOne();
}
public void play() {
Message<Boolean> message1 = new Message<>("x", Boolean.class, true, false, true);
Message<Integer> message2 = new Message<>("y", Integer.class, "Hello");
Result result1 = sendMessage(player, message1);
System.out.println("Response 1: " + result1.getResult());
Result result2 = sendMessage(player, message2);
System.out.println("Response 2: " + result2.getResult());
}
private Result sendMessage(Player player, Message<?> message1) {
return Optional.ofNullable(player)
.map(Game::createCommunicator)
.map(comm -> comm.executeCommand(message1))
.get();
}
public static void main(String[] args) {
Game game = new Game();
game.play();
}
private static PlayerCommunicator createCommunicator(Player player) {
if (player instanceof NativePlayer) {
return new NativePlayerCommunicator((NativePlayer) player);
}
return new ExternalPlayerCommunicator((ExternalPlayer) player);
}
}
public abstract class Player {}
public class ExternalPlayer extends Player {}
public abstract class NativePlayer extends Player {
abstract boolean x(Boolean a, Boolean b, Boolean c);
abstract Integer y(String yParam);
abstract Void z(Void zParam);
}
public abstract class PlayerCommunicator {
public abstract Result executeCommand(Message message);
}
import java.lang.reflect.Method;
public class NativePlayerCommunicator extends PlayerCommunicator {
private NativePlayer player;
public NativePlayerCommunicator(NativePlayer player) { this.player = player; }
public Result executeCommand(Message message) {
try {
Method method = player.getClass().getDeclaredMethod(message.getMethod(), message.getParamTypes());
return new Result(method.invoke(player, message.getArguments()));
} catch (Exception e) { throw new RuntimeException(e); }
}
}
public class ExternalPlayerCommunicator extends PlayerCommunicator {
private ExternalPlayer player;
public ExternalPlayerCommunicator(ExternalPlayer player) { this.player = player; }
@Override
public Result executeCommand(Message message) { /* Do some IO stuff */ return null; }
}
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class Message<OUT> {
private final String method;
private final Class<OUT> returnType;
private final Object[] arguments;
public Message(final String method, final Class<OUT> returnType, final Object... arguments) {
this.method = method;
this.returnType = returnType;
this.arguments = arguments;
}
public String getMethod() { return method; }
public Class<OUT> getReturnType() { return returnType; }
public Object[] getArguments() { return arguments; }
public Class[] getParamTypes() {
List<Class> classes = Arrays.stream(arguments).map(Object::getClass).collect(Collectors.toList());
Class[] classArray = Arrays.copyOf(classes.toArray(), classes.size(), Class[].class);
return classArray;
}
}
public class PlayerOne extends NativePlayer {
@Override
boolean x(Boolean a, Boolean b, Boolean c) {
System.out.println(String.format("x called: %b %b %b", a, b, c));
return a || b || c;
}
@Override
Integer y(String yParam) {
System.out.println("y called: " + yParam);
return yParam.length();
}
@Override
Void z(Void zParam) {
System.out.println("z called");
return null;
}
}
public class Result {
private final Object result;
public Result(Object result) { this.result = result; }
public Object getResult() { return result; }
}
(PS。今のところ、有用なものに完全に絞り込むことができないという私の心にある他のキーワード:Command Pattern、Visitor Pattern、java.lang.reflect.ParameterizedType)
PlayerComm extends Player
"の部分について混乱しています。すべてのJavaエントリが拡張されていますか?Player
このPlayerComm
クラスは非Javaエントリのアダプタですか?