2016-06-16 10 views
1

Ich schreibe Code für ein Universitätsprojekt. Wir müssen ein Brettspiel implementieren, das remote und im Multiplayer gespielt werden kann.Polymorphismus von Objekten durch einen Stream in Java?

Wir verwenden derzeit das Anfrage-Antwort-Muster: Die Clients senden die Anfragen über einen IO-Stream an den Server und der Server analysiert sie und gibt die richtigen Antworten zurück.

Das Problem ist, dass wir viele Arten von Anfragen, und wir verwenden Polymorphismus zu verstehen, welche Anforderung ist derjenige erhalten:

/** 
* This method is only functional to polymorphism: it should never be invoked. 
* @param request 
* @return only an assertion error 
*/ 
public ResponseMsg handleRequest(RequestMsg request) { 

    throw new AssertionError("It was created a RequestMsg. This should never happen.\n" 
} 

/** 
* The request is to change the map. 
* If the game is not started and the player is the first, the map will be changed and 
* a broadcast with the new map will be sent to all the players. 
* @param request: the request containing the name of the map chosen 
* @return An ack response message 
*/ 
public ResponseMsg handleRequest(ChangeMapRequestMsg request) { 

    if (game != null) 
     return new InvalidRequestMsg("You can't change the map when the game is already started"); 

    else if (request.getToken().getPlayerNumber() != 0) 
     return new InvalidRequestMsg("Only the first player can change the map"); 

    else { 

     this.map = request.getMap(); 

     BroadcastMsg broadcast = new ChangedMapBroadcastMsg(request.getMap()); 
     publisherInterface.publish(broadcast, getLobby()); 

     return new AckResponseMsg("Map changed successfully"); 
    } 
} 

/** 
* Handles a chat message 
* it sends a broadcast containing the message to all the players and an 
* acknowledgement to the player who sent it 
* 
* @param the chat request from the player 
* @return the acknowledgement 
*/ 
public ResponseMsg handleRequest(SendChatRequestMsg request) { 

    ChatBroadcastMsg chatBroadcast = new ChatBroadcastMsg(players.indexOf(request.getToken()), request.getMessage()); 
    publisherInterface.publish(chatBroadcast, getLobby()); 
    return new AckResponseMsg("Chat message sent.");   
} 

Das Problem ist, dass, wenn wir die Anforderungen an den Server senden, wir brauchen um sie durch einen Ausgabestrom zu leiten, und sie werden sie durch einen Eingabestrom lesen. Wir sind gezwungen, sie als Object zu bezeichnen, und somit verlieren wir die Möglichkeit, Polymorphie auszunutzen.

Wie können wir die Fähigkeit beibehalten, Polymorphie auszunutzen? Wir möchten instanceof nicht verwenden, um den dynamischen Typ der Anfrage zu erhalten, da unser Professor uns das nie gesagt hat.

+0

Können Sie das Objekt nicht einfach in die Basisanforderungsklasse (RequestMsg) umwandeln? Sie müssen den spezifischen Anfragetyp nicht kennen. – Eran

+0

Wir haben das getan und die Methode, die aufgerufen wurde, war immer die generische, während wir die spezifische benötigen. – Luvi

+0

Sind alle diese Methoden in der gleichen Klasse definiert? Welche Klasse ist das? – Eran

Antwort

0

Sie haben eine polymorphe Nachricht, aber Ihre Nachrichtenverarbeitung ist nicht polymorph. Es ist nur überladen.

Es gibt Möglichkeiten, die Nachrichtenverarbeitung zu vereinfachen.

Verschieben Sie die Verarbeitung auf die Nachricht selbst. Dann kann der Server nur eine in der Nachrichtenbasisklasse definierte Methode aufrufen (wobei der Server möglicherweise als Parameter übergeben wird). Die Methode kann dann die Verarbeitung oder delegieren zurück an die richtige Methode des Servers.

Alternativ, wenn die Nachrichten nicht wissen, wie sie verarbeitet werden, müssen Sie eine Form des Versands tun. Dies kann durch Erstellen ein Handler pro Nachrichtentyp durchgeführt werden, die alle eine gemeinsame Schnittstelle haben:

public interface MessageHandler { 
    public void process(MessageBase rawMessage); 
} 

Dann müssen Sie für jeden vorhandenen Nachrichtentyp einen konkreten Griff implementieren:

public class LoginHandler implements MessageHandler { 
    public void process(MessageBase rawMessage) { 
     LoginMessage msg = (LoginMessage) rawMessage; 
     // handling code 
    } 
} 

Die Nachrichtenverteilung kann dann entsprechend der Nachrichtenklasse ausgeführt werden, wenn Sie eine Zuordnung erstellen, die den Nachrichtentyp einem Handler zuordnet:

+0

Danke!Ich habe getan wie du vorgeschlagen hast und die Verarbeitung in die Nachrichten verschoben. Es funktionierte! – Luvi

1

Sie müssen überprüfen, ob das Objekt, das über den Stream gesendet wird, eine Instanz einer bestimmten Klasse ist und dann das Objekt in diese Klasse umwandeln.

Object obj = ...; // The object sent over the stream 
if(obj instanceof String) { 
    String str = (String) obj; // Cast it to String 
    ... 
} else if(obj instanceof Integer) { 
    Integer i = (Integer) obj; // Cast it to Integer 
    ... 
} 

Also, wenn ich ein String Objekt über den Stream senden war, die erste if-Anweisung laufen würde.