En PPCG, con frecuencia tenemos desafíos de King of the Hill , que enfrentan diferentes robots de código entre sí. No nos gusta limitar estos desafíos a un solo idioma, por lo que hacemos comunicación multiplataforma sobre E / S estándar.
Mi objetivo es escribir un marco que los escritores de desafíos puedan usar para facilitar la escritura de estos desafíos. He elaborado los siguientes requisitos que me gustaría cumplir:
El escritor de desafíos puede hacer una clase donde los métodos representan cada una de las comunicaciones distintas . Por ejemplo, en nuestro desafío Good vs Evil , el escritor haría una
Player
clase que tenga unabstract boolean vote(List<List<Boolean>> history)
método.El controlador puede proporcionar instancias de la clase anterior que se comunican a través de E / S estándar cuando se invocan los métodos mencionados anteriormente . Dicho esto, no todas las instancias de la clase anterior se comunicarán necesariamente a través de E / S estándar. 3 de los bots pueden ser bots nativos de Java (que simplemente anulan la
Player
clase, donde otros 2 están en otro idioma)Los métodos no siempre tendrán el mismo número de argumentos (ni siempre tendrán un valor de retorno)
Me gustaría que el escritor de desafíos tenga que hacer el menor trabajo posible para trabajar con mi marco.
No estoy en contra de usar la reflexión para resolver estos problemas. He considerado pedirle al escritor del desafío que haga algo como:
class PlayerComm extends Player {
private Communicator communicator;
public PlayerComm(Communicator communicator){
this.communicator = communicator;
}
@Override
boolean vote(List<List<Boolean>> history){
return (Boolean)communicator.sendMessage(history);
}
}
pero si hay varios métodos, esto puede ser bastante repetitivo, y el casting constante no es divertido. ( sendMessage
en este ejemplo aceptaría un número variable de Object
argumentos y devolvería un Object
)
¿Hay una mejor manera de hacer esto?
fuente
PlayerComm extends Player
". ¿Se están extendiendo todos los entrantes de JavaPlayer
, y estaPlayerComm
clase es un adaptador para entrantes que no son de Java?Respuestas:
OK, entonces las cosas se intensificaron y terminé con las siguientes diez clases ...
La conclusión de este método es que toda la comunicación ocurre usando la
Message
clase, es decir, el juego nunca llama a los métodos de los jugadores directamente, sino que siempre usa una clase de comunicador desde su marco. Hay un comunicador basado en la reflexión para las clases nativas de Java y luego debe haber un comunicador personalizado para todos los jugadores que no sean Java.Message<Integer> message = new Message<>("say", Integer.class, "Hello");
inicializaría un mensaje a un método nombradosay
con el parámetro que"Hello"
devuelve unInteger
. Esto luego se pasa a un comunicador (generado usando una fábrica basada en el tipo de jugador) que luego ejecuta el comando.(PD. Otras palabras clave en mi mente que no puedo refinar en algo útil en este momento: Patrón de comando , Patrón de visitante , java.lang.reflect.ParameterizedType )
fuente
Player
escribió escribaPlayerComm
. Si bien las interfaces del comunicador realizan la conversión automática para mí, todavía me encuentro con el mismo problema de tener que escribir la mismasendRequest()
función en cada método.