Bei PPCG gibt es häufig King of the Hill- Herausforderungen, bei denen verschiedene Code-Bots gegeneinander antreten. Wir möchten diese Herausforderungen nicht auf eine einzige Sprache beschränken, daher führen wir plattformübergreifende Kommunikation über Standard-E / A durch.
Mein Ziel ist es, ein Framework zu schreiben, mit dem Herausforderer diese Herausforderungen leichter schreiben können. Ich habe mir folgende Anforderungen ausgedacht, die ich erfüllen möchte:
Der Herausforderungsschreiber kann eine Klasse erstellen, in der Methoden jede der verschiedenen Kommunikationen darstellen . Zum Beispiel würde der Autor bei unserer Herausforderung Gut gegen Böse eine
Player
Klasse erstellen, die eineabstract boolean vote(List<List<Boolean>> history)
Methode enthält.Die Steuerung kann Instanzen der obigen Klasse bereitstellen, die über Standard-E / A kommunizieren, wenn die oben genannten Methoden aufgerufen werden . Allerdings kommunizieren nicht alle Instanzen der oben genannten Klasse notwendigerweise über Standard-E / A. 3 der Bots können native Java-Bots sein (die einfach die
Player
Klasse überschreiben , wobei weitere 2 in einer anderen Sprache vorliegen).Die Methoden haben nicht immer die gleiche Anzahl von Argumenten (noch haben sie immer einen Rückgabewert)
Ich möchte, dass der Herausforderer so wenig wie möglich arbeiten muss, um mit meinem Framework zu arbeiten.
Ich bin nicht dagegen, Reflexion zu verwenden, um diese Probleme zu lösen. Ich habe darüber nachgedacht, vom Herausforderungsschreiber Folgendes zu verlangen:
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);
}
}
Wenn es jedoch mehrere Methoden gibt, kann sich dies ziemlich wiederholen, und das ständige Casting macht keinen Spaß. ( sendMessage
In diesem Beispiel würde eine variable Anzahl von Object
Argumenten akzeptiert und ein zurückgegeben. Object
)
Gibt es einen besseren Weg, dies zu tun?
quelle
PlayerComm extends Player
" -Teil. Erweitern sich alle Java-TeilnehmerPlayer
, und diesePlayerComm
Klasse ist ein Adapter für Nicht-Java-Teilnehmer?Antworten:
OK, die Dinge eskalierten und ich bekam die folgenden zehn Klassen ...
Das Fazit dieser Methode ist, dass die gesamte Kommunikation über die
Message
Klasse erfolgt, dh das Spiel ruft niemals die Methoden der Spieler direkt auf, sondern verwendet immer eine Kommunikatorklasse aus Ihrem Framework. Es gibt einen reflexionsbasierten Kommunikator für native Java-Klassen und dann muss es einen benutzerdefinierten Kommunikator für alle Nicht-Java-Player geben.Message<Integer> message = new Message<>("say", Integer.class, "Hello");
würde eine Nachricht mit einer Methode initialisieren, deren Name einensay
Parameter"Hello"
zurückgibtInteger
. Dies wird dann an einen Kommunikator übergeben (der mithilfe einer Factory basierend auf dem Spielertyp generiert wurde), der dann den Befehl ausführt.(PS. Andere Schlüsselwörter in meinem Kopf, die ich momentan nicht ganz verfeinern kann: Befehlsmuster , Besuchermuster , java.lang.reflect.ParameterizedType )
quelle
Player
schreibtPlayerComm
. Während die Communicator-Schnittstellen für mich ein automatisches Casting durchführen, habe ich immer noch das gleiche Problem, dass ichsendRequest()
in jeder Methode dieselbe Funktion schreiben muss .