2016-04-21 11 views
0

Ich schreibe gerade einen Spieleserver.Nehmen Sie einen Polymorphismus-Ansatz?

Ich habe eine Klasse namens NetMessage. Diese Klasse fungiert als Vermittler zwischen Byte-Arrays, die über ein Netzwerk gesendet werden.

Wenn der Server das Byte-Array empfängt, wird es wieder in NetMessage geändert und erstellt eine Liste von diesen, die an einen Manager übergeben werden.

NetMessage ist eine abstrakte Klasse, so dass alle Nachrichten davon abstammen, aber wenn die Daten an GameManager ankommen, kann es sehr unterschiedliche Dinge mit den Daten tun, die es bekommt.

Zum Beispiel muss ein NetMoveMessage anders gehandhabt werden als ein NetConnectMessage.

Auch haben die Nachrichten selbst keine Methoden neben der Serialisierung selbst und können selbst den Zustand nicht ändern. Nur der Manager kann, also sind es im Wesentlichen nur Datenklassen.

Im Moment zu entscheiden, was mit den Daten zu tun ist, ich überprüfe einfach, welche Art von Nachricht es ist. Zum Beispiel

  NetMessage message = IncomingMessages.First.Value; 
      IncomingMessages.RemoveFirst(); 

      if(message is NetConnectMessage) 
      { 
       //cool things here 
      } 
      else if(message is NetMoveMessage) 
      { 
       //Isn't this exciting? 
      } 

Ist das eine schlechte Übung? Gibt es einen besseren Weg, dies zu tun? Es scheint mir in Ordnung zu sein, wenn man bedenkt, dass die Nachrichten nichts tun, also wäre die einzige Möglichkeit, die Daten zu lesen, herauszufinden, welche Daten gelesen werden müssen, und sie entsprechend zu behandeln. Wenn es eine offensichtliche bessere Herangehensweise gibt, die ich vermisse, aber fühle mich frei, mich aufzuklären.

Antwort

1

Sie könnten ein Wörterbuch verwenden, die für eine große Anzahl von Elementen wird schneller sein, aber langsamer für nur wenige aufgrund seiner Kopf ist

Dictionary<Type, Action<NetMessage>> messageHandlers = new Dictionary<Type, Action<NetMessage>>(); 

void RegisterHandler(Type type, Action<NetMessage> handler) 
{ 
    messageHandlers.Add(type, handler); 
} 

void MessageReceived(NetMessage message) 
{ 
    messageHandlers[message.GetType()].Invoke(message); 
} 

Sie können dann für Veranstaltungen registrieren Es mit

RegisterHandler(typeof(NetMessageSubClass), delegate(NetMessage message) 
{ 
    //NetMessageSubclass related stuff 
}); 

ist wahrscheinlich auch eine viel bessere Lösung mit Generika, aber ich kann nicht im Moment daran denken.


EDIT Hier ist die generische Methode

void RegisterHandler<T>(Action<T> handler) where T : NetMessage 
{ 
    messageHandlers.Add(
     typeof(T), 
     (NetMessage message) => handler.Invoke((T)message) 
    ); 
} 
1

Ja, es gibt sicherlich einen besseren Weg, dies zu tun. Dies ist ein perfektes Beispiel für die Verwendung von Polymorphismen.

Deklarieren Sie eine virtuelle Methode in Ihrer Basis abstrakte Klasse (NetMessage):

//sidenote, the method 
public virtual void DoCoolStuff(){} 

Und in der abgeleiteten Klassen (NetConnectMessage und NetMoveMessage) Überschreibung das Verfahren zu tun, was es für diese Klasse zu tun, muss in besonders.

public override void DoCoolStuff(){ 
    //make it do cool stuff :D 
} 

Und statt der vielen Wenn und anderes, können Sie es jetzt einfach so nennen:

NetMessage message = IncomingMessages.First.Value; 
IncomingMessages.RemoveFirst(); 
message.DoCoolStuff(); 

Das ist genau, wie Polymorphismus funktioniert: es tatsächlich zur Laufzeit, welche Art von Nachricht Ihre Nachricht bestimmen ist, und rufen Sie die entsprechende Methode entsprechend an.

+0

Die Sache die Nachrichten tun nichts ist. Alles, was eine Nachricht enthält, sind Daten, die sagen, was etwas tun will. Zum Beispiel kann eine Move-Nachricht eigentlich nichts bewegen, da sie keine Informationen über Spieler hat, um etwas zu tun. Der Server muss diese Dinge tatsächlich simulieren und dann neue Nachrichten schreiben, die basierend auf diesen Ereignissen gesendet werden. –

+0

Ah, okay. Dann verstehe ich nicht die Notwendigkeit, Nachrichtenklassen zu haben. Nun, egal welchen Ansatz Sie verwenden möchten, es wird irgendwo zu If/Else kommen (oder schreiben Sie eine Methode mit dem gleichen Namen, überladen sie ein anderes Argument für jede Art von Nachricht zu erhalten ist). – Vucko

Verwandte Themen