OK, mọi thứ đã leo thang và tôi đã kết thúc với mười lớp sau ...
Điểm mấu chốt trong phương thức này là tất cả các giao tiếp xảy ra khi sử dụng Message
lớp, tức là trò chơi không bao giờ gọi trực tiếp các phương thức của người chơi mà luôn sử dụng lớp giao tiếp từ khung của bạn. Có một trình truyền thông dựa trên sự phản chiếu cho các lớp Java gốc và sau đó phải có một trình truyền thông tùy chỉnh cho tất cả các trình phát không phải Java. Message<Integer> message = new Message<>("say", Integer.class, "Hello");
sẽ khởi tạo một thông điệp tới một phương thức có tên say
với tham số "Hello"
trả về một Integer
. Điều này sau đó được chuyển đến một bộ truyền thông (được tạo bằng cách sử dụng một nhà máy dựa trên loại trình phát) sau đó thực thi lệnh.
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. Các từ khóa khác trong tâm trí tôi hiện tại tôi không thể tinh chỉnh thành bất kỳ thứ gì hữu ích: Mẫu lệnh , Mẫu khách truy cập , java.lang.reflect.ParameterizedType )
PlayerComm extends Player
" -part. Có phải tất cả những người đăng ký Java đều mở rộngPlayer
vàPlayerComm
lớp này là một bộ điều hợp cho những người không tham gia Java?